[gimp] plug-ins: merge soc-2013-psd branch, squashed into one commit



commit fd997447e50a7e0c52da350c49ba52fe949a91db
Author: Simon Lui <simonlui src gnome org>
Date:   Wed Jun 19 13:15:52 2013 -0400

    plug-ins: merge soc-2013-psd branch, squashed into one commit
    
    This ports PSD loading/saving to GEGL and adds parsing of more
    PSD structs.

 plug-ins/file-psd/Makefile.am          |    1 +
 plug-ins/file-psd/psd-image-res-load.c |  252 ++++++++++++++----
 plug-ins/file-psd/psd-layer-res-load.c |  465 ++++++++++++++++++++++++++++----
 plug-ins/file-psd/psd-load.c           |  336 +++++++++++++++--------
 plug-ins/file-psd/psd-save.c           |  333 ++++++++++++-----------
 plug-ins/file-psd/psd.c                |    1 +
 plug-ins/file-psd/psd.h                |  144 +++++++++--
 7 files changed, 1138 insertions(+), 394 deletions(-)
---
diff --git a/plug-ins/file-psd/Makefile.am b/plug-ins/file-psd/Makefile.am
index 0297581..8b288e6 100644
--- a/plug-ins/file-psd/Makefile.am
+++ b/plug-ins/file-psd/Makefile.am
@@ -64,6 +64,7 @@ LDADD = \
        $(libgimpbase)          \
        $(JPEG_LIBS)            \
        $(GTK_LIBS)             \
+       $(GEGL_LIBS)            \
        $(EXIF_LIBS)            \
        $(IPTCDATA_LIBS)        \
        $(RT_LIBS)              \
diff --git a/plug-ins/file-psd/psd-image-res-load.c b/plug-ins/file-psd/psd-image-res-load.c
index db0153c..074eb64 100644
--- a/plug-ins/file-psd/psd-image-res-load.c
+++ b/plug-ins/file-psd/psd-image-res-load.c
@@ -75,11 +75,40 @@
   PSD_ALPHA_ID          = 1053,    Loaded     * 0x041d - Alpha IDs *
   PSD_URL_LIST_UNI      = 1054,               * 0x041e - URL list - unicode *
   PSD_VERSION_INFO      = 1057,               * 0x0421 - Version info *
-  PSD_EXIF_DATA         = 1058,    Loaded     * 0x0422 - Exif data block *
+  PSD_EXIF_DATA         = 1058,    Loaded     * 0x0422 - Exif data block 1 *
+  PSD_EXIF_DATA_3       = 1059                * 0X0423 - Exif data block 3 (?) *
   PSD_XMP_DATA          = 1060,    Loaded     * 0x0424 - XMP data block *
+  PSD_CAPTION_DIGEST    = 1061,               * 0x0425 - Caption digest *
+  PSD_PRINT_SCALE       = 1062,               * 0x0426 - Print scale *
+  PSD_PIXEL_AR          = 1064,               * 0x0428 - Pixel aspect ratio *
+  PSD_LAYER_COMPS       = 1065,               * 0x0429 - Layer comps *
+  PSD_ALT_DUOTONE_COLOR = 1066,               * 0x042A - Alternative Duotone colors *
+  PSD_ALT_SPOT_COLOR    = 1067,               * 0x042B - Alternative Spot colors *
+  PSD_LAYER_SELECT_ID   = 1069,               * 0x042D - Layer selection ID *
+  PSD_HDR_TONING_INFO   = 1070,               * 0x042E - HDR toning information *
+  PSD_PRINT_INFO_SCALE  = 1071,               * 0x042F - Print scale *
+  PSD_LAYER_GROUP_E_ID  = 1072,               * 0x0430 - Layer group(s) enabled ID *
+  PSD_COLOR_SAMPLER_NEW = 1073,               * 0x0431 - Color sampler resource for ps CS3 and higher PSD 
files *
+  PSD_MEASURE_SCALE     = 1074,               * 0x0432 - Measurement scale *
+  PSD_TIMELINE_INFO     = 1075,               * 0x0433 - Timeline information *
+  PSD_SHEET_DISCLOSE    = 1076,               * 0x0434 - Sheet discloser *
+  PSD_DISPLAY_INFO_NEW  = 1077,    Loaded     * 0x0435 - DisplayInfo structure for ps CS3 and higher PSD 
files *
+  PSD_ONION_SKINS       = 1078,               * 0x0436 - Onion skins *
+  PSD_COUNT_INFO        = 1080,               * 0x0438 - Count information*
+  PSD_PRINT_INFO        = 1082,               * 0x043A - Print information added in ps CS5*
+  PSD_PRINT_STYLE       = 1083,               * 0x043B - Print style *
+  PSD_MAC_NSPRINTINFO   = 1084,               * 0x043C - Mac NSPrintInfo*
+  PSD_WIN_DEVMODE       = 1085,               * 0x043D - Windows DEVMODE *
+  PSD_AUTO_SAVE_PATH    = 1086,               * 0x043E - Auto save file path *
+  PSD_AUTO_SAVE_FORMAT  = 1087,               * 0x043F - Auto save format *
   PSD_PATH_INFO_FIRST   = 2000,    Loaded     * 0x07d0 - First path info block *
   PSD_PATH_INFO_LAST    = 2998,    Loaded     * 0x0bb6 - Last path info block *
   PSD_CLIPPING_PATH     = 2999,               * 0x0bb7 - Name of clipping path *
+  PSD_PLUGIN_R_FIRST    = 4000,               * 0x0FA0 - First plugin resource *
+  PSD_PLUGIN_R_LAST     = 4999,               * 0x1387 - Last plugin resource *
+  PSD_IMAGEREADY_VARS   = 7000,    PS Only    * 0x1B58 - Imageready variables *
+  PSD_IMAGEREADY_DATA   = 7001,    PS Only    * 0x1B59 - Imageready data sets *
+  PSD_LIGHTROOM_WORK    = 8000,    PS Only    * 0x1F40 - Lightroom workflow *
   PSD_PRINT_FLAGS_2     = 10000               * 0x2710 - Print flags *
 */
 
@@ -193,6 +222,12 @@ static gint     load_resource_1058     (const PSDimageres     *res_a,
                                         FILE                  *f,
                                         GError               **error);
 
+static gint     load_resource_1077     (const PSDimageres     *res_a,
+                                        const gint32           image_id,
+                                        PSDimage              *img_a,
+                                        FILE                  *f,
+                                        GError               **error);
+
 static gint     load_resource_2000     (const PSDimageres     *res_a,
                                         const gint32           image_id,
                                         FILE                  *f,
@@ -254,7 +289,7 @@ load_image_resource (PSDimageres   *res_a,
       return -1;
     }
 
-   /* Process image resource blocks */
+  /* Process image resource blocks */
   if (memcmp (res_a->type, "8BIM", 4) != 0 &&
       memcmp (res_a->type, "MeSa", 4) !=0)
     {
@@ -349,6 +384,10 @@ load_image_resource (PSDimageres   *res_a,
           case PSD_XMP_DATA:
             break;
 
+          case PSD_DISPLAY_INFO_NEW:
+            load_resource_1077 (res_a, image_id, img_a, f, error);
+            break;
+
           default:
             if (res_a->id >= 2000 &&
                 res_a->id <  2999)
@@ -390,14 +429,14 @@ load_thumbnail_resource (PSDimageres   *res_a,
       return -1;
     }
 
-   /* Process image resource blocks */
- if (res_a->id == PSD_THUMB_RES
-     || res_a->id == PSD_THUMB_RES2)
-   {
-        /* Load thumbnails from standard file load */
-        load_resource_1033 (res_a, image_id, f, error);
-        rtn = 1;
-   }
+  /* Process image resource blocks */
+  if (res_a->id == PSD_THUMB_RES
+      || res_a->id == PSD_THUMB_RES2)
+    {
+      /* Load thumbnails from standard file load */
+      load_resource_1033 (res_a, image_id, f, error);
+      rtn = 1;
+    }
 
   /* Image blocks are null padded to even length */
   if (res_a->data_len % 2 == 0)
@@ -439,7 +478,7 @@ load_resource_unknown (const PSDimageres  *res_a,
     }
 
   name = g_strdup_printf ("psd-image-resource-%.4s-%.4x",
-                            res_a->type, res_a->id);
+                           res_a->type, res_a->id);
   IFDBG(2) g_debug ("Parasite name: %s", name);
 
   parasite = gimp_parasite_new (name, 0, res_a->data_len, data);
@@ -474,7 +513,7 @@ load_resource_ps_only (const PSDimageres  *res_a,
     }
 
   name = g_strdup_printf ("psd-image-resource-%.4s-%.4x",
-                            res_a->type, res_a->id);
+                           res_a->type, res_a->id);
   IFDBG(2) g_debug ("Parasite name: %s", name);
 
   parasite = gimp_parasite_new (name, 0, res_a->data_len, data);
@@ -519,12 +558,12 @@ load_resource_1005 (const PSDimageres  *res_a,
   res_info.heightUnit = GINT16_FROM_BE (res_info.heightUnit);
 
   IFDBG(3) g_debug ("Resolution: %d, %d, %d, %d, %d, %d",
-                      res_info.hRes,
-                      res_info.hResUnit,
-                      res_info.widthUnit,
-                      res_info.vRes,
-                      res_info.vResUnit,
-                      res_info.heightUnit);
+                     res_info.hRes,
+                     res_info.hResUnit,
+                     res_info.widthUnit,
+                     res_info.vRes,
+                     res_info.vResUnit,
+                     res_info.heightUnit);
 
   /* Resolution always recorded as pixels / inch in a fixed point implied
      decimal int32 with 16 bits before point and 16 after (i.e. cast as
@@ -535,14 +574,14 @@ load_resource_1005 (const PSDimageres  *res_a,
   /* GIMP only has one display unit so use ps horizontal resolution unit */
   switch (res_info.hResUnit)
     {
-      case PSD_RES_INCH:
-        image_unit = GIMP_UNIT_INCH;
-        break;
-      case PSD_RES_CM:
-        image_unit = GIMP_UNIT_MM;
-        break;
-      default:
-        image_unit = GIMP_UNIT_INCH;
+    case PSD_RES_INCH:
+      image_unit = GIMP_UNIT_INCH;
+      break;
+    case PSD_RES_CM:
+      image_unit = GIMP_UNIT_MM;
+      break;
+    default:
+      image_unit = GIMP_UNIT_INCH;
     }
 
   gimp_image_set_unit (image_id, image_unit);
@@ -681,13 +720,13 @@ load_resource_1007 (const PSDimageres  *res_a,
       gimp_rgb_set_alpha (&gimp_rgb, 1.0);
 
       IFDBG(2) g_debug ("PS cSpace: %d, col: %d %d %d %d, opacity: %d, kind: %d",
-             dsp_info.colorSpace, ps_color.cmyk.cyan, ps_color.cmyk.magenta,
-             ps_color.cmyk.yellow, ps_color.cmyk.black, dsp_info.opacity,
-             dsp_info.kind);
+                        dsp_info.colorSpace, ps_color.cmyk.cyan, ps_color.cmyk.magenta,
+                        ps_color.cmyk.yellow, ps_color.cmyk.black, dsp_info.opacity,
+                        dsp_info.kind);
 
       IFDBG(2) g_debug ("cSpace: %d, col: %g %g %g, opacity: %d, kind: %d",
-             dsp_info.colorSpace, gimp_rgb.r * 255 , gimp_rgb.g * 255,
-             gimp_rgb.b * 255, dsp_info.opacity, dsp_info.kind);
+                        dsp_info.colorSpace, gimp_rgb.r * 255 , gimp_rgb.g * 255,
+                        gimp_rgb.b * 255, dsp_info.opacity, dsp_info.kind);
 
       img_a->alpha_display_info[cidx] = g_malloc (sizeof (PSDchanneldata));
       img_a->alpha_display_info[cidx]->gimp_color = gimp_rgb;
@@ -748,8 +787,8 @@ load_resource_1022 (const PSDimageres  *res_a,
   img_a->quick_mask_id = GUINT16_FROM_BE (img_a->quick_mask_id);
 
   IFDBG(3) g_debug ("Quick mask channel: %d, empty: %d",
-                      img_a->quick_mask_id,
-                      quick_mask_empty);
+                    img_a->quick_mask_id,
+                    quick_mask_empty);
 
   return 0;
 }
@@ -913,8 +952,8 @@ load_resource_1033 (const PSDimageres  *res_a,
   struct jpeg_error_mgr         jerr;
 
   ThumbnailInfo         thumb_info;
-  GimpDrawable         *drawable;
-  GimpPixelRgn          pixel_rgn;
+  GeglBuffer           *buffer;
+  const Babl           *format;
   gint32                layer_id;
   guchar               *buf;
   guchar               *rgb_buf;
@@ -948,9 +987,9 @@ load_resource_1033 (const PSDimageres  *res_a,
   IFDBG(2) g_debug ("\nThumbnail:\n"
                     "\tFormat: %d\n"
                     "\tDimensions: %d x %d\n",
-                      thumb_info.format,
-                      thumb_info.width,
-                      thumb_info.height);
+                     thumb_info.format,
+                     thumb_info.width,
+                     thumb_info.height);
 
   if (thumb_info.format != 1)
     {
@@ -995,9 +1034,8 @@ load_resource_1033 (const PSDimageres  *res_a,
                              cinfo.output_width,
                              cinfo.output_height,
                              GIMP_RGB_IMAGE, 100, GIMP_NORMAL_MODE);
-  drawable = gimp_drawable_get (layer_id);
-  gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
-                       drawable->width, drawable->height, TRUE, FALSE);
+  buffer = gimp_drawable_get_buffer (layer_id);
+  format = babl_format ("R'G'B'A u8");
 
   /* Step 6: while (scan lines remain to be read) */
   /*           jpeg_read_scanlines(...); */
@@ -1011,7 +1049,7 @@ load_resource_1033 (const PSDimageres  *res_a,
           guchar *dst = rgb_buf;
           guchar *src = buf;
 
-          for (i = 0; i < drawable->width * drawable->height; ++i)
+          for (i = 0; i < gegl_buffer_get_width (buffer) * gegl_buffer_get_height (buffer); ++i)
             {
               guchar r, g, b;
 
@@ -1023,8 +1061,8 @@ load_resource_1033 (const PSDimageres  *res_a,
               *(dst++) = r;
             }
         }
-      gimp_pixel_rgn_set_rect (&pixel_rgn, rgb_buf ? rgb_buf : buf,
-                               0, 0, drawable->width, drawable->height);
+      gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (buffer), gegl_buffer_get_height 
(buffer)),
+                       0, format, rgb_buf ? rgb_buf : buf, GEGL_AUTO_ROWSTRIDE);
     }
 
   /* Step 7: Finish decompression */
@@ -1046,7 +1084,7 @@ load_resource_1033 (const PSDimageres  *res_a,
    * jerr.num_warnings is nonzero).
    */
   gimp_image_insert_layer (image_id, layer_id, -1, 0);
-  gimp_drawable_detach (drawable);
+  g_object_unref (buffer);
 
   return 0;
 }
@@ -1233,6 +1271,118 @@ load_resource_1058 (const PSDimageres  *res_a,
 }
 
 static gint
+load_resource_1077 (const PSDimageres  *res_a,
+                    const gint32        image_id,
+                    PSDimage           *img_a,
+                    FILE               *f,
+                    GError            **error)
+{
+  /* Load alpha channel display info */
+
+  DisplayInfoNew    dsp_info;
+  CMColor           ps_color;
+  GimpRGB           gimp_rgb;
+  GimpHSV           gimp_hsv;
+  GimpCMYK          gimp_cmyk;
+  gint16            tot_rec;
+  gint              cidx;
+
+  IFDBG(2) g_debug ("Process image resource block 1077: Display Info New");
+
+  /* For now, skip first 4 bytes since intention is unclear. Seems to be
+     a version number that is always one, but who knows. */
+  fseek (f, 4, SEEK_CUR);
+
+  tot_rec = res_a->data_len / 13;
+  if (tot_rec == 0)
+    return 0;
+
+  img_a->alpha_display_info = g_new (PSDchanneldata *, tot_rec);
+  img_a->alpha_display_count = tot_rec;
+  for (cidx = 0; cidx < tot_rec; ++cidx)
+    {
+      if (fread (&dsp_info.colorSpace, 2, 1, f) < 1
+          || fread (&dsp_info.color, 8, 1, f) < 1
+          || fread (&dsp_info.opacity, 2, 1, f) < 1
+          || fread (&dsp_info.mode, 1, 1, f) < 1)
+        {
+          psd_set_error (feof (f), errno, error);
+          return -1;
+        }
+      dsp_info.colorSpace = GINT16_FROM_BE (dsp_info.colorSpace);
+      ps_color.cmyk.cyan = GUINT16_FROM_BE (dsp_info.color[0]);
+      ps_color.cmyk.magenta = GUINT16_FROM_BE (dsp_info.color[1]);
+      ps_color.cmyk.yellow = GUINT16_FROM_BE (dsp_info.color[2]);
+      ps_color.cmyk.black = GUINT16_FROM_BE (dsp_info.color[3]);
+      dsp_info.opacity = GINT16_FROM_BE (dsp_info.opacity);
+
+      switch (dsp_info.colorSpace)
+        {
+          case PSD_CS_RGB:
+            gimp_rgb_set (&gimp_rgb, ps_color.rgb.red / 65535.0,
+                          ps_color.rgb.green / 65535.0,
+                          ps_color.rgb.blue / 65535.0);
+            break;
+
+          case PSD_CS_HSB:
+            gimp_hsv_set (&gimp_hsv, ps_color.hsv.hue / 65535.0,
+                          ps_color.hsv.saturation / 65535.0,
+                          ps_color.hsv.value / 65535.0);
+            gimp_hsv_to_rgb (&gimp_hsv, &gimp_rgb);
+            break;
+
+          case PSD_CS_CMYK:
+            gimp_cmyk_set (&gimp_cmyk, 1.0 - ps_color.cmyk.cyan / 65535.0,
+                           1.0 - ps_color.cmyk.magenta / 65535.0,
+                           1.0 - ps_color.cmyk.yellow / 65535.0,
+                           1.0 - ps_color.cmyk.black / 65535.0);
+            gimp_cmyk_to_rgb (&gimp_cmyk, &gimp_rgb);
+            break;
+
+          case PSD_CS_GRAYSCALE:
+            gimp_rgb_set (&gimp_rgb, ps_color.gray.gray / 10000.0,
+                          ps_color.gray.gray / 10000.0,
+                          ps_color.gray.gray / 10000.0);
+            break;
+
+          case PSD_CS_FOCOLTONE:
+          case PSD_CS_TRUMATCH:
+          case PSD_CS_HKS:
+          case PSD_CS_LAB:
+          case PSD_CS_PANTONE:
+          case PSD_CS_TOYO:
+          case PSD_CS_DIC:
+          case PSD_CS_ANPA:
+          default:
+            if (CONVERSION_WARNINGS)
+              g_message ("Unsupported color space: %d",
+                          dsp_info.colorSpace);
+            gimp_rgb_set (&gimp_rgb, 1.0, 0.0, 0.0);
+        }
+
+      gimp_rgb_set_alpha (&gimp_rgb, 1.0);
+
+      IFDBG(2) g_debug ("PS cSpace: %d, col: %d %d %d %d, opacity: %d, kind: %d",
+                        dsp_info.colorSpace, ps_color.cmyk.cyan, ps_color.cmyk.magenta,
+                        ps_color.cmyk.yellow, ps_color.cmyk.black, dsp_info.opacity,
+                        dsp_info.kind);
+
+      IFDBG(2) g_debug ("cSpace: %d, col: %g %g %g, opacity: %d, kind: %d",
+                        dsp_info.colorSpace, gimp_rgb.r * 255 , gimp_rgb.g * 255,
+                        gimp_rgb.b * 255, dsp_info.opacity, dsp_info.kind);
+
+      img_a->alpha_display_info[cidx] = g_malloc (sizeof (PSDchanneldata));
+      img_a->alpha_display_info[cidx]->gimp_color = gimp_rgb;
+      img_a->alpha_display_info[cidx]->opacity = dsp_info.opacity;
+      img_a->alpha_display_info[cidx]->ps_mode = dsp_info.mode;
+      img_a->alpha_display_info[cidx]->ps_cspace = dsp_info.colorSpace;
+      img_a->alpha_display_info[cidx]->ps_color = ps_color;
+    }
+
+  return 0;
+}
+
+static gint
 load_resource_2000 (const PSDimageres  *res_a,
                     const gint32        image_id,
                     FILE               *f,
@@ -1377,11 +1527,11 @@ load_resource_2000 (const PSDimageres  *res_a,
                   || type == PSD_PATH_OP_UNLNK)
                 {
                   if (fread (&y[0], 4, 1, f) < 1
-                    || fread (&x[0], 4, 1, f) < 1
-                    || fread (&y[1], 4, 1, f) < 1
-                    || fread (&x[1], 4, 1, f) < 1
-                    || fread (&y[2], 4, 1, f) < 1
-                    || fread (&x[2], 4, 1, f) < 1)
+                      || fread (&x[0], 4, 1, f) < 1
+                      || fread (&y[1], 4, 1, f) < 1
+                      || fread (&x[1], 4, 1, f) < 1
+                      || fread (&y[2], 4, 1, f) < 1
+                      || fread (&x[2], 4, 1, f) < 1)
                     {
                       psd_set_error (feof (f), errno, error);
                       return -1;
@@ -1429,5 +1579,5 @@ load_resource_2000 (const PSDimageres  *res_a,
       path_rec--;
     }
 
- return 0;
+  return 0;
 }
diff --git a/plug-ins/file-psd/psd-layer-res-load.c b/plug-ins/file-psd/psd-layer-res-load.c
index f98377f..2c82d23 100644
--- a/plug-ins/file-psd/psd-layer-res-load.c
+++ b/plug-ins/file-psd/psd-layer-res-load.c
@@ -22,7 +22,7 @@
   All layer resources not otherwise handled, including unknown types
   are dropped with a warning.
 
- * Adjustment layer IDs *
+  * Adjustment layer IDs *
   PSD_LADJ_LEVEL          "levl"    Drop Layer  * Adjustment layer - levels (PS4) *
   PSD_LADJ_CURVE          "curv"    Drop Layer  * Adjustment layer - curves (PS4) *
   PSD_LADJ_BRIGHTNESS     "brit"    Drop Layer  * Adjustment layer - brightness contrast (PS4) *
@@ -38,21 +38,23 @@
   PSD_LADJ_INVERT         "nvrt"    Drop Layer  * Adjustment layer - invert (PS4) *
   PSD_LADJ_THRESHOLD      "thrs"    Drop Layer  * Adjustment layer - threshold (PS4) *
   PSD_LADJ_POSTERIZE      "post"    Drop Layer  * Adjustment layer - posterize (PS4) *
+  PSD_LADJ_VIBRANCE       "vibA"        -       * Adjustment layer - vibrance (PS10) *
+  PSD_LADJ_COLOR_LOOKUP   "clrL"        -       * Adjustment layer - color lookup (PS13) *
 
- * Fill Layer IDs *
+  * Fill Layer IDs *
   PSD_LFIL_SOLID          "SoCo"        -       * Solid color sheet setting (PS6) *
   PSD_LFIL_PATTERN        "PtFl"        -       * Pattern fill setting (PS6) *
   PSD_LFIL_GRADIENT       "GdFl"        -       * Gradient fill setting (PS6) *
 
- * Effects Layer IDs *
+  * Effects Layer IDs *
   PSD_LFX_FX              "lrFX"        -       * Effects layer info (PS5) *
   PSD_LFX_FX2             "lfx2"        -       * Object based effects layer info (PS6) *
 
- * Type Tool Layers *
+  * Type Tool Layers *
   PSD_LTYP_TYPE           "tySh"        -       * Type tool layer (PS5) *
   PSD_LTYP_TYPE2          "TySh"        -       * Type tool object setting (PS6) *
 
- * Layer Properties *
+  * Layer Properties *
   PSD_LPRP_UNICODE        "luni"     Loaded     * Unicode layer name (PS5) *
   PSD_LPRP_SOURCE         "lnsr"     Loaded     * Layer name source setting (PS6) *
   PSD_LPRP_ID             "lyid"     Loaded     * Layer ID (PS5) *
@@ -63,13 +65,13 @@
   PSD_LPRP_COLOR          "lclr"        -       * Sheet color setting (PS6) *
   PSD_LPRP_REF_POINT      "fxrp"        -       * Reference point (PS6) *
 
- * Vector mask *
+  * Vector mask *
   PSD_LMSK_VMASK          "vmsk"        -       * Vector mask setting (PS6) *
 
- * Parasites *
+  * Parasites *
   PSD_LPAR_ANNOTATE       "Anno"        -       * Annotation (PS6) *
 
- * Other *
+  * Other *
   PSD_LOTH_PATTERN        "Patt"        -       * Patterns (PS6) *
   PSD_LOTH_GRADIENT       "grdm"        -       * Gradient settings (PS6) *
   PSD_LOTH_SECTION        "lsct"     Loaded     * Section divider setting (PS6) (Layer Groups) *
@@ -78,14 +80,42 @@
   PSD_LOTH_PATT_DATA      "shpa"        -       * Pattern data (PS6) *
   PSD_LOTH_META_DATA      "shmd"        -       * Meta data setting (PS6) *
   PSD_LOTH_LAYER_DATA     "layr"        -       * Layer data (PS6) *
-
- * Effects layer resource IDs *
+  PSD_LOTH_CONTENT_GEN    "CgEd"        -       * Content generator extra data (PS12) *
+  PSD_LOTH_TEXT_ENGINE    "Txt2"        -       * Text engine data (PS10) *
+  PSD_LOTH_PATH_NAME      "pths"        -       * Unicode path name (PS13) *
+  PSD_LOTH_ANIMATION_FX   "anFX"        -       * Animation effects (PS13) *
+  PSD_LOTH_FILTER_MASK    "FMsk"        -       * Filter mask (PS10) *
+  PSD_LOTH_VECTOR_STROKE  "vscg"        -       * Vector stroke data (PS13) *
+  PSD_LOTH_ALIGN_RENDER   "sn2P"        -       * Aligned rendering flag (?) *
+  PSD_LOTH_USER_MASK      "LMsk"        -       * User mask (?) *
+
+  * Effects layer resource IDs *
   PSD_LFX_COMMON          "cmnS"        -       * Effects layer - common state (PS5) *
   PSD_LFX_DROP_SDW        "dsdw"        -       * Effects layer - drop shadow (PS5) *
   PSD_LFX_INNER_SDW       "isdw"        -       * Effects layer - inner shadow (PS5) *
   PSD_LFX_OUTER_GLW       "oglw"        -       * Effects layer - outer glow (PS5) *
   PSD_LFX_INNER_GLW       "iglw"        -       * Effects layer - inner glow (PS5) *
   PSD_LFX_BEVEL           "bevl"        -       * Effects layer - bevel (PS5) *
+
+  * New stuff temporarily until I can get them sorted out *
+
+  * Placed Layer *
+ PSD_LPL_PLACE_LAYER      "plLd"        -       * Placed layer (?) *
+ PSD_LPL_PLACE_LAYER_NEW  "SoLd"        -       * Placed layer (PS10) *
+
+ * Linked Layer *
+ PSD_LLL_LINKED_LAYER     "lnkD"        -       * Linked layer (?) *
+ PSD_LLL_LINKED_LAYER_2   "lnk2"        -       * Linked layer 2nd key *
+ PSD_LLL_LINKED_LAYER_3   "lnk3"        -       * Linked layer 3rd key *
+
+ * Merged Transparency *
+ PSD_LMT_MERGE_TRANS      "Mtrn"        -       * Merged transperency save flag (?) *
+ PSD_LMT_MERGE_TRANS_16   "Mt16"        -       * Merged transperency save flag 2 *
+ PSD_LMT_MERGE_TRANS_32   "Mt32"        -       * Merged transperency save flag 3 *
+
+ * Filter Effects *
+ PSD_LFFX_FILTER_FX       "FXid"        -       * Filter effects (?) *
+ PSD_LFFX_FILTER_FX_2     "FEid"        -       * Filter effects 2 *
 */
 
 #include "config.h"
@@ -143,6 +173,10 @@ static gint     load_resource_lsct    (const PSDlayerres     *res_a,
                                        FILE                  *f,
                                        GError               **error);
 
+static gint     load_resource_lrfx    (const PSDlayerres     *res_a,
+                                      PSDlayer              *lyr_a,
+                                      FILE                  *f,
+                                      GError               **error);
 
 /* Public Functions */
 gint
@@ -161,7 +195,7 @@ get_layer_resource_header (PSDlayerres  *res_a,
   res_a->data_start = ftell (f);
 
   IFDBG(2) g_debug ("Sig: %.4s, key: %.4s, start: %d, len: %d",
-                     res_a->sig, res_a->key, res_a->data_start, res_a->data_len);
+                    res_a->sig, res_a->key, res_a->data_start, res_a->data_len);
 
   return 0;
 }
@@ -179,7 +213,7 @@ load_layer_resource (PSDlayerres  *res_a,
       return -1;
     }
 
-   /* Process layer resource blocks */
+  /* Process layer resource blocks */
   if (memcmp (res_a->sig, "8BIM", 4) != 0)
     {
       IFDBG(1) g_debug ("Unknown layer resource signature %.4s", res_a->sig);
@@ -201,30 +235,32 @@ load_layer_resource (PSDlayerres  *res_a,
           || memcmp (res_a->key, PSD_LADJ_THRESHOLD, 4) == 0
           || memcmp (res_a->key, PSD_LADJ_INVERT, 4) == 0
           || memcmp (res_a->key, PSD_LADJ_POSTERIZE, 4) == 0)
-            load_resource_ladj (res_a, lyr_a, f, error);
+       load_resource_ladj (res_a, lyr_a, f, error);
 
       else if (memcmp (res_a->key, PSD_LFIL_SOLID, 4) == 0
-          || memcmp (res_a->key, PSD_LFIL_PATTERN, 4) == 0
-          || memcmp (res_a->key, PSD_LFIL_GRADIENT, 4) == 0)
-            load_resource_lfil (res_a, lyr_a, f, error);
+              || memcmp (res_a->key, PSD_LFIL_PATTERN, 4) == 0
+              || memcmp (res_a->key, PSD_LFIL_GRADIENT, 4) == 0)
+       load_resource_lfil (res_a, lyr_a, f, error);
 
       else if (memcmp (res_a->key, PSD_LFX_FX, 4) == 0
-          || memcmp (res_a->key, PSD_LFX_FX2, 4) == 0)
-            load_resource_lfx (res_a, lyr_a, f, error);
+              || memcmp (res_a->key, PSD_LFX_FX2, 4) == 0)
+       load_resource_lfx (res_a, lyr_a, f, error);
 
       else if (memcmp (res_a->key, PSD_LTYP_TYPE, 4) == 0
-          || memcmp (res_a->key, PSD_LTYP_TYPE2, 4) == 0)
-            load_resource_ltyp (res_a, lyr_a, f, error);
+              || memcmp (res_a->key, PSD_LTYP_TYPE2, 4) == 0)
+       load_resource_ltyp (res_a, lyr_a, f, error);
 
       else if (memcmp (res_a->key, PSD_LPRP_UNICODE, 4) == 0)
-            load_resource_luni (res_a, lyr_a, f, error);
+       load_resource_luni (res_a, lyr_a, f, error);
 
       else if (memcmp (res_a->key, PSD_LPRP_ID, 4) == 0)
-            load_resource_lyid (res_a, lyr_a, f, error);
+       load_resource_lyid (res_a, lyr_a, f, error);
 
       else if (memcmp (res_a->key, PSD_LOTH_SECTION, 4) == 0)
-            load_resource_lsct (res_a, lyr_a, f, error);
+       load_resource_lsct (res_a, lyr_a, f, error);
 
+      else if (memcmp (res_a->key, PSD_LFX_FX, 4) == 0)
+       load_resource_lrfx (res_a, lyr_a, f, error);
       else
         load_resource_unknown (res_a, lyr_a, f, error);
     }
@@ -329,18 +365,15 @@ load_resource_ltyp (const PSDlayerres  *res_a,
   gint16            version;
   gint16            text_desc_vers;
   gint32            desc_version;
+  gint32            read_len;
+  gint32            write_len;
   guint64           t_xx;
   guint64           t_xy;
   guint64           t_yx;
   guint64           t_yy;
   guint64           t_tx;
   guint64           t_ty;
-  gdouble           transform_xx;
-  gdouble           transform_xy;
-  gdouble           transform_yx;
-  gdouble           transform_yy;
-  gdouble           transform_tx;
-  gdouble           transform_ty;
+  gchar            *classID;
 
   static gboolean   msg_flag = FALSE;
 
@@ -374,31 +407,30 @@ load_resource_ltyp (const PSDlayerres  *res_a,
       version = GINT16_FROM_BE (version);
       text_desc_vers = GINT16_FROM_BE (text_desc_vers);
       desc_version = GINT32_FROM_BE (desc_version);
-//      t_xx = GUINT64_FROM_BE (t_xx);
-//      t_xy = GUINT64_FROM_BE (t_xy);
-//      t_yx = GUINT64_FROM_BE (t_yx);
-//      t_yy = GUINT64_FROM_BE (t_yy);
-//      t_tx = GUINT64_FROM_BE (t_tx);
-//      t_ty = GUINT64_FROM_BE (t_ty);
-
-      transform_xx = t_xx >> 11;
-      transform_xy = t_xy >> 11;
-      transform_yx = t_yx >> 11;
-      transform_yy = t_yy >> 11;
-      transform_tx = t_tx >> 11;
-      transform_ty = t_ty >> 11;
+      //      t_xx = GUINT64_FROM_BE (t_xx);
+      //      t_xy = GUINT64_FROM_BE (t_xy);
+      //      t_yx = GUINT64_FROM_BE (t_yx);
+      //      t_yy = GUINT64_FROM_BE (t_yy);
+      //      t_tx = GUINT64_FROM_BE (t_tx);
+      //      t_ty = GUINT64_FROM_BE (t_ty);
+
+      lyr_a->text.xx = t_xx >> 11;
+      lyr_a->text.xy = t_xy >> 11;
+      lyr_a->text.yx = t_yx >> 11;
+      lyr_a->text.yy = t_yy >> 11;
+      lyr_a->text.tx = t_tx >> 11;
+      lyr_a->text.ty = t_ty >> 11;
 
       IFDBG(2) g_debug ("Version: %d, Text desc. vers.: %d, Desc. vers.: %d",
                         version, text_desc_vers, desc_version);
 
       IFDBG(2) g_debug ("Transform\n\txx: %f\n\txy: %f\n\tyx: %f"
                         "\n\tyy: %f\n\ttx: %f\n\tty: %f",
-                        transform_xx, transform_xy, transform_yx,
-                        transform_yy, transform_tx, transform_ty);
-
-//      classID = fread_unicode_string (&read_len, &write_len, 4, f);
-//      IFDBG(2) g_debug ("Unicode name: %s", classID);
+                        lyr_a->text.xx, lyr_a->text.xy, lyr_a->text.yx,
+                        lyr_a->text.yy, lyr_a->text.tx, lyr_a->text.ty);
 
+      classID = fread_unicode_string (&read_len, &write_len, 4, f, error);
+      IFDBG(2) g_debug ("Unicode name: %s", classID);
     }
 
   return 0;
@@ -472,3 +504,342 @@ load_resource_lsct (const PSDlayerres  *res_a,
   return 0;
 }
 
+static gint
+load_resource_lrfx (const PSDlayerres  *res_a,
+                    PSDlayer           *lyr_a,
+                    FILE               *f,
+                    GError            **error)
+{
+  gint16    version;
+  gint16    count;
+  gchar     signature[4];
+  gchar     effectname[4];
+  gint      i;
+
+  IFDBG(2) g_debug ("Process layer resource block %.4s: Layer effects", res_a->key);
+
+  if (fread (&version, 2, 1, f) < 1
+      || fread (&count, 2, 1, f) < 1)
+    {
+      psd_set_error (feof (f), errno, error);
+      return -1;
+    }
+
+  for (i = 0; i < count; i++)
+    {
+      if (fread (&signature, 4, 1, f) < 1
+          || fread(&effectname, 4, 1, f) < 1)
+        {
+          psd_set_error (feof (f), errno, error);
+          return -1;
+        }
+
+      if (memcmp (signature, "8BIM", 4) != 0)
+        {
+          IFDBG(1) g_debug ("Unknown layer resource signature %.4s", signature);
+        }
+      else
+        {
+          if (memcmp (effectname, "cmnS", 4) == 0)
+            {
+              gint32    size;
+              gint32    ver;
+              gchar     visible;
+              gint16    unused;
+
+              if (fread (&size, 4, 1, f) < 1
+                  || fread(&ver, 4, 1, f) < 1
+                  || fread(&visible, 1, 1, f) < 1
+                  || fread(&unused, 2, 1, f) < 1)
+               {
+                 psd_set_error (feof (f), errno, error);
+                 return -1;
+               }
+            }
+          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];
+
+              if (fread (&size, 4, 1, f) < 1
+                  || fread(&ver, 4, 1, f) < 1
+                  || fread(&blur, 4, 1, f) < 1
+                  || fread(&intensity, 4, 1, f) < 1
+                  || fread(&angle, 4, 1, f) < 1
+                  || fread(&distance, 4, 1, f) < 1
+                  || fread(&color[0], 2, 1, f) < 1
+                  || fread(&color[1], 2, 1, f) < 1
+                  || fread(&color[2], 2, 1, f) < 1
+                  || fread(&color[3], 2, 1, f) < 1
+                  || fread(&color[4], 2, 1, f) < 1
+                  || fread(&blendsig, 4, 1, f) < 1
+                  || fread(&effect, 4, 1, f) < 1
+                  || fread(&effecton, 1, 1, f) < 1
+                  || fread(&anglefx, 1, 1, f) < 1
+                  || fread(&opacity, 1, 1, f) < 1
+                  || fread(&natcolor[0], 2, 1, f) < 1
+                  || fread(&natcolor[1], 2, 1, f) < 1
+                  || fread(&natcolor[2], 2, 1, f) < 1
+                  || fread(&natcolor[3], 2, 1, f) < 1
+                  || fread(&natcolor[4], 2, 1, f) < 1)
+                {
+                  psd_set_error (feof (f), errno, error);
+                  return -1;
+                }
+            }
+          else if (memcmp (effectname, "oglw", 4) == 0)
+            {
+              gint32    size;
+              gint32    ver;
+              gint32    blur;
+              gint32    intensity;
+              gint16    color[5];
+              gint32    blendsig;
+              gint32    effect;
+              gchar     effecton;
+              gchar     opacity;
+              gint16    natcolor[5];
+
+              if (fread (&size, 4, 1, f) < 1
+                  || fread(&ver, 4, 1, f) < 1
+                  || fread(&blur, 4, 1, f) < 1
+                  || fread(&intensity, 4, 1, f) < 1
+                  || fread(&color[0], 2, 1, f) < 1
+                  || fread(&color[1], 2, 1, f) < 1
+                  || fread(&color[2], 2, 1, f) < 1
+                  || fread(&color[3], 2, 1, f) < 1
+                  || fread(&color[4], 2, 1, f) < 1
+                  || fread(&blendsig, 4, 1, f) < 1
+                  || fread(&effect, 4, 1, f) < 1
+                  || fread(&effecton, 1, 1, f) < 1
+                  || fread(&opacity, 1, 1, f) < 1)
+                {
+                  psd_set_error (feof (f), errno, error);
+                  return -1;
+                }
+
+              if (ver == 42)
+                {
+                  if (fread(&natcolor[0], 2, 1, f) < 1
+                      || fread(&natcolor[1], 2, 1, f) < 1
+                      || fread(&natcolor[2], 2, 1, f) < 1
+                      || fread(&natcolor[3], 2, 1, f) < 1
+                      || fread(&natcolor[4], 2, 1, f) < 1)
+                    {
+                      psd_set_error (feof (f), errno, error);
+                      return -1;
+                    }
+                }
+            }
+          else if (memcmp (effectname, "iglw", 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];
+
+              if (fread (&size, 4, 1, f) < 1
+                  || fread(&ver, 4, 1, f) < 1
+                  || fread(&blur, 4, 1, f) < 1
+                  || fread(&intensity, 4, 1, f) < 1
+                  || fread(&angle, 4, 1, f) < 1
+                  || fread(&distance, 4, 1, f) < 1
+                  || fread(&color[0], 2, 1, f) < 1
+                  || fread(&color[1], 2, 1, f) < 1
+                  || fread(&color[2], 2, 1, f) < 1
+                  || fread(&color[3], 2, 1, f) < 1
+                  || fread(&color[4], 2, 1, f) < 1
+                  || fread(&blendsig, 4, 1, f) < 1
+                  || fread(&effect, 4, 1, f) < 1
+                  || fread(&effecton, 1, 1, f) < 1
+                  || fread(&anglefx, 1, 1, f) < 1
+                  || fread(&opacity, 1, 1, f) < 1
+                  || fread(&natcolor[0], 2, 1, f) < 1
+                  || fread(&natcolor[1], 2, 1, f) < 1
+                  || fread(&natcolor[2], 2, 1, f) < 1
+                  || fread(&natcolor[3], 2, 1, f) < 1
+                  || fread(&natcolor[4], 2, 1, f) < 1)
+                {
+                  psd_set_error (feof (f), errno, error);
+                  return -1;
+                }
+            }
+          else if (memcmp (effectname, "oglw", 4) == 0)
+            {
+              gint32    size;
+              gint32    ver;
+              gint32    blur;
+              gint32    intensity;
+              gint16    color[5];
+              gint32    blendsig;
+              gint32    effect;
+              gchar     effecton;
+              gchar     opacity;
+              gchar     invert;
+              gint16    natcolor[5];
+
+              if (fread (&size, 4, 1, f) < 1
+                  || fread(&ver, 4, 1, f) < 1
+                  || fread(&blur, 4, 1, f) < 1
+                  || fread(&intensity, 4, 1, f) < 1
+                  || fread(&color[0], 2, 1, f) < 1
+                  || fread(&color[1], 2, 1, f) < 1
+                  || fread(&color[2], 2, 1, f) < 1
+                  || fread(&color[3], 2, 1, f) < 1
+                  || fread(&color[4], 2, 1, f) < 1
+                  || fread(&blendsig, 4, 1, f) < 1
+                  || fread(&effect, 4, 1, f) < 1
+                  || fread(&effecton, 1, 1, f) < 1
+                  || fread(&opacity, 1, 1, f) < 1)
+                {
+                  psd_set_error (feof (f), errno, error);
+                  return -1;
+                }
+
+              if (ver == 43)
+                {
+                  if (fread (&invert, 1, 1, f) < 1
+                      || fread(&natcolor[0], 2, 1, f) < 1
+                      || fread(&natcolor[0], 2, 1, f) < 1
+                      || fread(&natcolor[1], 2, 1, f) < 1
+                      || fread(&natcolor[2], 2, 1, f) < 1
+                      || fread(&natcolor[3], 2, 1, f) < 1
+                      || fread(&natcolor[4], 2, 1, f) < 1)
+                    {
+                      psd_set_error (feof (f), errno, error);
+                      return -1;
+                    }
+                }
+            }
+          else if (memcmp (effectname, "bevl", 4) == 0)
+            {
+              gint32    size;
+              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 (fread (&size, 4, 1, f) < 1
+                  || fread(&ver, 4, 1, f) < 1
+                  || fread(&angle, 4, 1, f) < 1
+                  || fread(&strength, 4, 1, f) < 1
+                  || fread(&blur, 4, 1, f) < 1
+                  || fread(&highlightsig, 4, 1, f) < 1
+                  || fread(&highlighteffect, 4, 1, f) < 1
+                  || fread(&shadowsig, 4, 1, f) < 1
+                  || fread(&highlightcolor[0], 2, 1, f) < 1
+                  || fread(&shadoweffect, 4, 1, f) < 1
+                  || fread(&highlightcolor[1], 2, 1, f) < 1
+                  || fread(&highlightcolor[2], 2, 1, f) < 1
+                  || fread(&highlightcolor[3], 2, 1, f) < 1
+                  || fread(&highlightcolor[4], 2, 1, f) < 1
+                  || fread(&shadowcolor[0], 2, 1, f) < 1
+                  || fread(&shadowcolor[1], 2, 1, f) < 1
+                  || fread(&shadowcolor[2], 2, 1, f) < 1
+                  || fread(&shadowcolor[3], 2, 1, f) < 1
+                  || fread(&shadowcolor[4], 2, 1, f) < 1
+                  || fread(&style, 1, 1, f) < 1
+                  || fread(&highlightopacity, 1, 1, f) < 1
+                  || fread(&shadowopacity, 1, 1, f) < 1
+                  || fread(&enabled, 1, 1, f) < 1
+                  || fread(&global, 1, 1, f) < 1
+                  || fread(&direction, 1, 1, f) < 1)
+                {
+                  psd_set_error (feof (f), errno, error);
+                  return -1;
+                }
+
+              if (ver == 78)
+                {
+                  if (fread(&highlightnatcolor[0], 2, 1, f) < 1
+                      || fread(&highlightnatcolor[0], 2, 1, f) < 1
+                      || fread(&highlightnatcolor[1], 2, 1, f) < 1
+                      || fread(&highlightnatcolor[2], 2, 1, f) < 1
+                      || fread(&highlightnatcolor[3], 2, 1, f) < 1
+                      || fread(&highlightnatcolor[4], 2, 1, f) < 1
+                      || fread(&shadownatcolor[0], 2, 1, f) < 1
+                      || fread(&shadownatcolor[0], 2, 1, f) < 1
+                      || fread(&shadownatcolor[1], 2, 1, f) < 1
+                      || fread(&shadownatcolor[2], 2, 1, f) < 1
+                      || fread(&shadownatcolor[3], 2, 1, f) < 1
+                      || fread(&shadownatcolor[4], 2, 1, f) < 1)
+                    {
+                      psd_set_error (feof (f), errno, error);
+                      return -1;
+                    }
+                }
+            }
+          else if (memcmp (effectname, "sofi", 4) == 0)
+            {
+              gint32    size;
+              gint32    ver;
+              gint32    key;
+              gint16    color[5];
+              gchar     opacity;
+              gchar     enabled;
+              gint16    natcolor[5];
+
+              if (fread (&size, 4, 1, f) < 1
+                  || fread(&ver, 4, 1, f) < 1
+                  || fread(&key, 4, 1, f) < 1
+                  || fread(&color[0], 2, 1, f) < 1
+                  || fread(&color[1], 2, 1, f) < 1
+                  || fread(&color[2], 2, 1, f) < 1
+                  || fread(&color[3], 2, 1, f) < 1
+                  || fread(&color[4], 2, 1, f) < 1
+                  || fread(&opacity, 1, 1, f) < 1
+                  || fread(&enabled, 1, 1, f) < 1
+                  || fread(&natcolor[0], 2, 1, f) < 1
+                  || fread(&natcolor[1], 2, 1, f) < 1
+                  || fread(&natcolor[2], 2, 1, f) < 1
+                  || fread(&natcolor[3], 2, 1, f) < 1
+                  || fread(&natcolor[4], 2, 1, f) < 1)
+                {
+                  psd_set_error (feof (f), errno, error);
+                  return -1;
+                }
+            }
+          else
+            {
+              IFDBG(1) g_debug ("Unknown layer effect signature %.4s", effectname);
+            }
+        }
+    }
+
+  return 0;
+}
diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c
index 5c556d6..8c19c3d 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -97,15 +97,13 @@ static gint             read_channel_data          (PSDchannel     *channel,
                                                     FILE           *f,
                                                     GError        **error);
 
-static void             convert_16_bit             (const gchar *src,
-                                                    gchar       *dst,
-                                                    guint32      len);
-
 static void             convert_1_bit              (const gchar *src,
                                                     gchar       *dst,
                                                     guint32      rows,
                                                     guint32      columns);
 
+static const Babl*      get_pixel_format           (PSDimage    *img_a);
+
 
 /* Main file load function */
 gint32
@@ -326,16 +324,15 @@ read_header_block (PSDimage  *img_a,
       return -1;
     }
 
-  /* Warnings for format conversions */
+  /* Warning for unsupported bit depth */
   switch (img_a->bps)
     {
+      case 32:
+        IFDBG(3) g_debug ("32 Bit Data");
+        break;
+
       case 16:
         IFDBG(3) g_debug ("16 Bit Data");
-        if (CONVERSION_WARNINGS)
-          g_message (_("Warning:\n"
-                       "The image you are loading has 16 bits per channel. GIMP "
-                       "can only handle 8 bit, so it will be converted for you. "
-                       "Information will be lost because of this conversion."));
         break;
 
       case 8:
@@ -484,6 +481,7 @@ read_layer_block (PSDimage  *img_a,
       img_a->num_layers = -1;
       return NULL;
     }
+
   img_a->mask_layer_len = GUINT32_FROM_BE (block_len);
 
   IFDBG(1) g_debug ("Layer and mask block size = %d", img_a->mask_layer_len);
@@ -525,6 +523,7 @@ read_layer_block (PSDimage  *img_a,
 
           /* Create pointer array for the layer records */
           lyr_a = g_new (PSDlayer *, img_a->num_layers);
+
           for (lidx = 0; lidx < img_a->num_layers; ++lidx)
             {
               /* Allocate layer record */
@@ -544,6 +543,7 @@ read_layer_block (PSDimage  *img_a,
                   psd_set_error (feof (f), errno, error);
                   return NULL;
                 }
+
               lyr_a[lidx]->top = GINT32_FROM_BE (lyr_a[lidx]->top);
               lyr_a[lidx]->left = GINT32_FROM_BE (lyr_a[lidx]->left);
               lyr_a[lidx]->bottom = GINT32_FROM_BE (lyr_a[lidx]->bottom);
@@ -590,6 +590,7 @@ read_layer_block (PSDimage  *img_a,
                                  lyr_a[lidx]->num_channels);
 
               lyr_a[lidx]->chn_info = g_new (ChannelLengthInfo, lyr_a[lidx]->num_channels);
+
               for (cidx = 0; cidx < lyr_a[lidx]->num_channels; ++cidx)
                 {
                   if (fread (&lyr_a[lidx]->chn_info[cidx].channel_id, 2, 1, f) < 1
@@ -630,6 +631,7 @@ read_layer_block (PSDimage  *img_a,
 
               lyr_a[lidx]->layer_flags.trans_prot = lyr_a[lidx]->flags & 1 ? TRUE : FALSE;
               lyr_a[lidx]->layer_flags.visible = lyr_a[lidx]->flags & 2 ? FALSE : TRUE;
+
               if (lyr_a[lidx]->flags & 8)
                 lyr_a[lidx]->layer_flags.irrelevant = lyr_a[lidx]->flags & 16 ? TRUE : FALSE;
               else
@@ -802,9 +804,11 @@ read_layer_block (PSDimage  *img_a,
                   psd_set_error (feof (f), errno, error);
                   return NULL;
                 }
+
               block_len = GUINT32_FROM_BE (block_len);
               block_rem -= (block_len + 4);
               IFDBG(3) g_debug ("Remaining length %d", block_rem);
+
               if (block_len > 0)
                 {
                   if (fseek (f, block_len, SEEK_CUR) < 0)
@@ -818,6 +822,7 @@ read_layer_block (PSDimage  *img_a,
                                                        4, f, error);
               if (*error)
                 return NULL;
+
               block_rem -= read_len;
               IFDBG(3) g_debug ("Remaining length %d", block_rem);
 
@@ -827,8 +832,13 @@ read_layer_block (PSDimage  *img_a,
                 {
                   if (get_layer_resource_header (&res_a, f, error) < 0)
                     return NULL;
+
                   block_rem -= 12;
 
+                 //Round up to the nearest even byte
+                 while (res_a.data_len % 4 != 0)
+                   res_a.data_len++;
+
                   if (res_a.data_len > block_rem)
                     {
                       IFDBG(1) g_debug ("Unexpected end of layer resource data");
@@ -902,6 +912,7 @@ create_gimp_image (PSDimage    *img_a,
                    const gchar *filename)
 {
   gint32 image_id = -1;
+  GimpPrecision precision;
 
   switch (img_a->color_mode)
     {
@@ -926,10 +937,32 @@ create_gimp_image (PSDimage    *img_a,
         break;
     }
 
+    switch (img_a->bps)
+      {
+        case 32:
+          precision = GIMP_PRECISION_U32_LINEAR;
+         break;
+
+        case 16:
+          precision = GIMP_PRECISION_U16_LINEAR;
+         break;
+
+        case 8:
+        case 1:
+          precision = GIMP_PRECISION_U8_LINEAR;
+         break;
+
+        default:
+         /* Precision not supported */
+         g_warning ("Invalid precision");
+         return -1;
+         break;
+      }
+
   /* Create gimp image */
   IFDBG(2) g_debug ("Create image");
-  image_id = gimp_image_new (img_a->columns, img_a->rows, img_a->base_type);
-
+  image_id = gimp_image_new_with_precision (img_a->columns, img_a->rows,
+                                           img_a->base_type, precision);
   gimp_image_set_filename (image_id, filename);
   gimp_image_undo_disable (image_id);
 
@@ -1025,6 +1058,7 @@ add_layers (const gint32  image_id,
   guint16               layer_channels;
   guint16               channel_idx[MAX_CHANNELS];
   guint16              *rle_pack_len;
+  guint16               bps;
   gint32                l_x;                   /* Layer x */
   gint32                l_y;                   /* Layer y */
   gint32                l_w;                   /* Layer width */
@@ -1045,8 +1079,7 @@ add_layers (const gint32  image_id,
   gboolean              user_mask;
   gboolean              empty;
   gboolean              empty_mask;
-  GimpDrawable         *drawable;
-  GimpPixelRgn          pixel_rgn;
+  GeglBuffer           *buffer;
   GimpImageType         image_type;
   GimpLayerModeEffects  layer_mode;
 
@@ -1092,25 +1125,25 @@ add_layers (const gint32  image_id,
         }
       else
         {
-          if (lyr_a[lidx]->group_type != 0)
-            {
-              if (lyr_a[lidx]->group_type == 3)
-                {
-                  /* the </Layer group> marker layers are used to
-                     assemble the layer structure in a single pass */
-                  layer_id = gimp_layer_group_new (image_id);
-                }
-              else /* group-type == 1 || group_type == 2 */
-                {
-                  layer_id = g_array_index (parent_group_stack, gint32,
-                                            parent_group_stack->len-1);
-                  /* since the layers are stored in reverse, the group
-                     layer start marker actually means we're done with
-                     that layer group */
-                  g_array_remove_index (parent_group_stack,
-                                        parent_group_stack->len-1);
-                }
-            }
+         if (lyr_a[lidx]->group_type != 0)
+           {
+             if (lyr_a[lidx]->group_type == 3)
+               {
+               /* the </Layer group> marker layers are used to
+                  assemble the layer structure in a single pass */
+               layer_id = gimp_layer_group_new (image_id);
+               }
+             else /* group-type == 1 || group_type == 2 */
+               {
+                 layer_id = g_array_index (parent_group_stack, gint32,
+                                           parent_group_stack->len-1);
+                 /* since the layers are stored in reverse, the group
+                    layer start marker actually means we're done with
+                    that layer group */
+                 g_array_remove_index (parent_group_stack,
+                                       parent_group_stack->len-1);
+               }
+           }
 
           /* Empty layer */
           if (lyr_a[lidx]->bottom - lyr_a[lidx]->top == 0
@@ -1228,7 +1261,7 @@ add_layers (const gint32  image_id,
                         g_free (rle_pack_len);
                         break;
 
-                      case PSD_COMP_ZIP:                 /* ? */
+                     case PSD_COMP_ZIP:                 /* ? */
                       case PSD_COMP_ZIP_PRED:
                       default:
                         g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
@@ -1292,20 +1325,15 @@ add_layers (const gint32  image_id,
               else
                 {
                   IFDBG(2) g_debug ("End group layer id %d.", layer_id);
-                  drawable = gimp_drawable_get (layer_id);
                   layer_mode = psd_to_gimp_blend_mode (lyr_a[lidx]->blend_mode);
                   gimp_layer_set_mode (layer_id, layer_mode);
                   gimp_layer_set_opacity (layer_id, 
                                           lyr_a[lidx]->opacity * 100 / 255);
-                  gimp_item_set_name (drawable->drawable_id, lyr_a[lidx]->name);
+                  gimp_item_set_name (layer_id, lyr_a[lidx]->name);
                   g_free (lyr_a[lidx]->name);
-                  gimp_item_set_visible (drawable->drawable_id,
-                                         lyr_a[lidx]->layer_flags.visible);
+                  gimp_item_set_visible (layer_id, lyr_a[lidx]->layer_flags.visible);
                   if (lyr_a[lidx]->id)
-                    gimp_item_set_tattoo (drawable->drawable_id,
-                                          lyr_a[lidx]->id);
-                  gimp_drawable_flush (drawable);
-                  gimp_drawable_detach (drawable);
+                    gimp_item_set_tattoo (layer_id, lyr_a[lidx]->id);
                 }
             }
           else if (empty)
@@ -1317,15 +1345,12 @@ add_layers (const gint32  image_id,
                                          image_type, 0, GIMP_NORMAL_MODE);
               g_free (lyr_a[lidx]->name);
               gimp_image_insert_layer (image_id, layer_id, parent_group_id, -1);
-              drawable = gimp_drawable_get (layer_id);
-              gimp_drawable_fill (drawable->drawable_id, GIMP_TRANSPARENT_FILL);
-              gimp_item_set_visible (drawable->drawable_id, lyr_a[lidx]->layer_flags.visible);
+              gimp_drawable_fill (layer_id, GIMP_TRANSPARENT_FILL);
+              gimp_item_set_visible (layer_id, lyr_a[lidx]->layer_flags.visible);
               if (lyr_a[lidx]->id)
-                gimp_item_set_tattoo (drawable->drawable_id, lyr_a[lidx]->id);
+                gimp_item_set_tattoo (layer_id, lyr_a[lidx]->id);
               if (lyr_a[lidx]->layer_flags.irrelevant)
-                gimp_item_set_visible (drawable->drawable_id, FALSE);
-              gimp_drawable_flush (drawable);
-              gimp_drawable_detach (drawable);
+                gimp_item_set_visible (layer_id, FALSE);
             }
           else
             {
@@ -1338,12 +1363,16 @@ add_layers (const gint32  image_id,
               image_type = get_gimp_image_type (img_a->base_type, alpha);
               IFDBG(3) g_debug ("Layer type %d", image_type);
               layer_size = l_w * l_h;
-              pixels = g_malloc (layer_size * layer_channels);
+             bps = img_a->bps / 8;
+             if (bps == 0)
+               bps++;
+              pixels = g_malloc (layer_size * layer_channels * bps);
               for (cidx = 0; cidx < layer_channels; ++cidx)
                 {
                   IFDBG(3) g_debug ("Start channel %d", channel_idx[cidx]);
                   for (i = 0; i < layer_size; ++i)
-                    pixels[(i * layer_channels) + cidx] = lyr_chn[channel_idx[cidx]]->data[i];
+                   memcpy (&pixels[((i * layer_channels) + cidx) * bps],
+                           &lyr_chn[channel_idx[cidx]]->data[i * bps], bps);
                   g_free (lyr_chn[channel_idx[cidx]]->data);
                 }
 
@@ -1356,16 +1385,13 @@ add_layers (const gint32  image_id,
               gimp_image_insert_layer (image_id, layer_id, parent_group_id, -1);
               gimp_layer_set_offsets (layer_id, l_x, l_y);
               gimp_layer_set_lock_alpha  (layer_id, lyr_a[lidx]->layer_flags.trans_prot);
-              drawable = gimp_drawable_get (layer_id);
-              gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
-                                   drawable->width, drawable->height, TRUE, FALSE);
-              gimp_pixel_rgn_set_rect (&pixel_rgn, pixels,
-                                       0, 0, drawable->width, drawable->height);
-              gimp_item_set_visible (drawable->drawable_id, lyr_a[lidx]->layer_flags.visible);
+             buffer = gimp_drawable_get_buffer (layer_id);
+             gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (buffer), 
gegl_buffer_get_height (buffer)),
+                              0, get_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
+              gimp_item_set_visible (layer_id, lyr_a[lidx]->layer_flags.visible);
               if (lyr_a[lidx]->id)
-                gimp_item_set_tattoo (drawable->drawable_id, lyr_a[lidx]->id);
-              gimp_drawable_flush (drawable);
-              gimp_drawable_detach (drawable);
+                gimp_item_set_tattoo (layer_id, lyr_a[lidx]->id);
+              g_object_unref (buffer);
               g_free (pixels);
             }
 
@@ -1463,12 +1489,10 @@ add_layers (const gint32  image_id,
 
                   IFDBG(3) g_debug ("New layer mask %d", mask_id);
                   gimp_layer_add_mask (layer_id, mask_id);
-                  drawable = gimp_drawable_get (mask_id);
-                  gimp_pixel_rgn_init (&pixel_rgn, drawable, 0 , 0,
-                                       drawable->width, drawable->height, TRUE, FALSE);
-                  gimp_pixel_rgn_set_rect (&pixel_rgn, pixels, lm_x, lm_y, lm_w, lm_h);
-                  gimp_drawable_flush (drawable);
-                  gimp_drawable_detach (drawable);
+                 buffer = gimp_drawable_get_buffer (mask_id);
+                 gegl_buffer_set (buffer, GEGL_RECTANGLE (lm_x, lm_y, lm_w, lm_h), 0,
+                                  get_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
+                  g_object_unref (buffer);
                   gimp_layer_set_apply_mask (layer_id,
                     ! lyr_a[lidx]->layer_mask.mask_flags.disabled);
                   g_free (pixels);
@@ -1500,6 +1524,7 @@ add_merged_image (const gint32  image_id,
   guint16               base_channels;
   guint16               extra_channels;
   guint16               total_channels;
+  guint16               bps;
   guint16              *rle_pack_len[MAX_CHANNELS];
   guint32               alpha_id;
   gint32                layer_size;
@@ -1514,13 +1539,15 @@ add_merged_image (const gint32  image_id,
   gint                  offset;
   gint                  i;
   gboolean              alpha_visible;
-  GimpDrawable         *drawable;
-  GimpPixelRgn          pixel_rgn;
+  GeglBuffer           *buffer;
   GimpImageType         image_type;
   GimpRGB               alpha_rgb;
 
   total_channels = img_a->channels;
   extra_channels = 0;
+  bps = img_a->bps / 8;
+  if (bps == 0)
+    bps++;
 
   if ((img_a->color_mode == PSD_BITMAP ||
        img_a->color_mode == PSD_GRAYSCALE ||
@@ -1626,12 +1653,13 @@ add_merged_image (const gint32  image_id,
       image_type = get_gimp_image_type (img_a->base_type, img_a->transparency);
 
       layer_size = img_a->columns * img_a->rows;
-      pixels = g_malloc (layer_size * base_channels);
+      pixels = g_malloc (layer_size * base_channels * bps);
       for (cidx = 0; cidx < base_channels; ++cidx)
         {
           for (i = 0; i < layer_size; ++i)
             {
-              pixels[(i * base_channels) + cidx] = chn_a[cidx].data[i];
+             memcpy (&pixels[((i * base_channels) + cidx) * bps],
+                     &chn_a[cidx].data[i * bps], bps);
             }
           g_free (chn_a[cidx].data);
         }
@@ -1643,13 +1671,10 @@ add_merged_image (const gint32  image_id,
                                  image_type,
                                  100, GIMP_NORMAL_MODE);
       gimp_image_insert_layer (image_id, layer_id, -1, 0);
-      drawable = gimp_drawable_get (layer_id);
-      gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
-                           drawable->width, drawable->height, TRUE, FALSE);
-      gimp_pixel_rgn_set_rect (&pixel_rgn, pixels,
-                               0, 0, drawable->width, drawable->height);
-      gimp_drawable_flush (drawable);
-      gimp_drawable_detach (drawable);
+      buffer = gimp_drawable_get_buffer (layer_id);
+      gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (buffer), gegl_buffer_get_height 
(buffer)),
+                      0, get_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
+      g_object_unref (buffer);
       g_free (pixels);
     }
   else
@@ -1734,18 +1759,14 @@ add_merged_image (const gint32  image_id,
                                          alpha_opacity, &alpha_rgb);
           gimp_image_insert_channel (image_id, channel_id, -1, 0);
           g_free (alpha_name);
-          drawable = gimp_drawable_get (channel_id);
+          buffer = gimp_drawable_get_buffer (channel_id);
           if (alpha_id)
-            gimp_item_set_tattoo (drawable->drawable_id, alpha_id);
-          gimp_item_set_visible (drawable->drawable_id, alpha_visible);
-          gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
-                                drawable->width, drawable->height,
-                                TRUE, FALSE);
-          gimp_pixel_rgn_set_rect (&pixel_rgn, pixels,
-                                   0, 0, drawable->width,
-                                   drawable->height);
-          gimp_drawable_flush (drawable);
-          gimp_drawable_detach (drawable);
+            gimp_item_set_tattoo (channel_id, alpha_id);
+          gimp_item_set_visible (channel_id, alpha_visible);
+         gegl_buffer_set (buffer,
+                          GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (buffer), gegl_buffer_get_height 
(buffer)),
+                          0, get_pixel_format (img_a), pixels, GEGL_AUTO_ROWSTRIDE);
+          g_object_unref (buffer);
           g_free (chn_a[cidx].data);
         }
 
@@ -1928,20 +1949,21 @@ read_channel_data (PSDchannel     *channel,
   /* Convert channel data to GIMP format */
   switch (bps)
     {
+      case 32:
       case 16:
-        channel->data = (gchar *) g_malloc (channel->rows * channel->columns);
-        convert_16_bit (raw_data, channel->data, (channel->rows * channel->columns) << 1);
-        break;
-
       case 8:
-        channel->data = (gchar *) g_malloc (channel->rows * channel->columns);
-        memcpy (channel->data, raw_data, (channel->rows * channel->columns));
+        channel->data = (gchar *) g_malloc (channel->rows * channel->columns * bps / 8 );
+        memcpy (channel->data, raw_data, (channel->rows * channel->columns * bps / 8));
         break;
 
       case 1:
         channel->data = (gchar *) g_malloc (channel->rows * channel->columns);
         convert_1_bit (raw_data, channel->data, channel->rows, channel->columns);
         break;
+
+      default:
+       return -1;
+        break;
     }
 
   g_free (raw_data);
@@ -1950,27 +1972,6 @@ read_channel_data (PSDchannel     *channel,
 }
 
 static void
-convert_16_bit (const gchar *src,
-                gchar       *dst,
-                guint32     len)
-{
-/* Convert 16 bit to 8 bit dropping low byte
-*/
-  gint      i;
-
-  IFDBG(3)  g_debug ("Start 16 bit conversion");
-
-  for (i = 0; i < len >> 1; ++i)
-    {
-      *dst = *src;
-      dst++;
-      src += 2;
-    }
-
-  IFDBG(3)  g_debug ("End 16 bit conversion");
-}
-
-static void
 convert_1_bit (const gchar *src,
                gchar       *dst,
                guint32      rows,
@@ -2002,3 +2003,108 @@ convert_1_bit (const gchar *src,
     }
   IFDBG(3)  g_debug ("End 1 bit conversion");
 }
+
+static const Babl*
+get_pixel_format (PSDimage *img_a)
+{
+  const Babl *format;
+
+  switch (get_gimp_image_type (img_a->base_type, img_a->transparency))
+    {
+    case GIMP_GRAY_IMAGE:
+      switch (img_a->bps)
+       {
+       case 32:
+          format = babl_format ("Y u32");
+         break;
+
+        case 16:
+          format = babl_format ("Y u16");
+         break;
+
+        case 8:
+        case 1:
+          format = babl_format ("Y u8");
+         break;
+
+        default:
+          return NULL;
+         break;
+       }
+      break;
+
+    case GIMP_GRAYA_IMAGE:
+      switch (img_a->bps)
+       {
+       case 32:
+          format = babl_format ("YA u32");
+         break;
+
+        case 16:
+          format = babl_format ("YA u16");
+          break;
+
+        case 8:
+        case 1:
+          format = babl_format ("YA u8");
+          break;
+
+        default:
+         return NULL;
+         break;
+       }
+      break;
+
+    case GIMP_RGB_IMAGE:
+    case GIMP_INDEXED_IMAGE:
+      switch (img_a->bps)
+       {
+       case 32:
+          format = babl_format ("RGB u32");
+         break;
+
+        case 16:
+          format = babl_format ("RGB u16");
+          break;
+
+        case 8:
+        case 1:
+          format = babl_format ("RGB u8");
+          break;
+
+        default:
+         return NULL;
+         break;
+       }
+      break;
+
+    case GIMP_RGBA_IMAGE:
+    case GIMP_INDEXEDA_IMAGE:
+      switch (img_a->bps)
+       {
+       case 32:
+          format = babl_format ("RGBA u32");
+         break;
+
+        case 16:
+          format = babl_format ("RGBA u16");
+         break;
+
+        case 8:
+        case 1:
+          format = babl_format ("RGBA u8");
+          break;
+
+        default:
+         return NULL;
+         break;
+       }
+      break;
+
+    default:
+      return NULL;
+      break;
+    }
+
+  return format;
+}
diff --git a/plug-ins/file-psd/psd-save.c b/plug-ins/file-psd/psd-save.c
index 9ffec9c..1d78b96 100644
--- a/plug-ins/file-psd/psd-save.c
+++ b/plug-ins/file-psd/psd-save.c
@@ -86,12 +86,11 @@
 #define DEBUG FALSE
 
 /* 1: Normal debuggin, 2: Deep debuggin */
-#define DEBUG_LEVEL 1
+#define DEBUG_LEVEL 2
 
 #define IFDBG if (DEBUG)
 #define IF_DEEP_DBG if (DEBUG && DEBUG_LEVEL == 2)
 
-
 #define PSD_UNIT_INCH 1
 #define PSD_UNIT_CM   2
 
@@ -101,7 +100,6 @@
 /* Local types etc
  */
 
-
 typedef struct PsdLayerDimension
 {
   gint   left;
@@ -110,7 +108,6 @@ typedef struct PsdLayerDimension
   gint32 height;
 } PSD_Layer_Dimension;
 
-
 typedef struct PsdImageData
 {
   gboolean             compression;
@@ -134,64 +131,80 @@ typedef struct PsdImageData
 
 static PSD_Image_Data PSDImageData;
 
-
 /* Declare some local functions.
  */
 
-static void   query                (void);
-static void   run                  (const gchar      *name,
-                                    gint              nparams,
-                                    const GimpParam  *param,
-                                    gint             *nreturn_vals,
-                                    GimpParam       **return_vals);
-
-static void   psd_lmode_layer      (gint32         idLayer,
-                                    gchar         *psdMode);
-static void   reshuffle_cmap_write (guchar        *mapGimp);
-static void   save_header          (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_layer_and_mask  (FILE          *fd,
-                                    gint32         image_id);
-static void   save_data            (FILE          *fd,
-                                    gint32         image_id);
-static gint   save_image           (const gchar   *filename,
-                                    gint32         image_id,
-                                    GError       **error);
-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_string         (FILE          *fd,
-                                    const gchar   *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_gint32         (FILE          *fd,
-                                    gint32         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 gint32 create_merged_image  (gint32         imageID);
+static void        query                (void);
+
+static void        run                  (const gchar         *name,
+                                        gint                 nparams,
+                                        const GimpParam     *param,
+                                        gint                *nreturn_vals,
+                                        GimpParam           **return_vals);
+
+static void        psd_lmode_layer      (gint32               idLayer,
+                                        gchar               *psdMode);
+
+static void        reshuffle_cmap_write (guchar              *mapGimp);
+
+static void        save_header          (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_layer_and_mask  (FILE                *fd,
+                                        gint32               image_id);
+
+static void        save_data            (FILE                *fd,
+                                        gint32               image_id);
+
+static gint        save_image           (const gchar         *filename,
+                                        gint32               image_id,
+                                        GError             **error);
+
+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_string         (FILE               *fd,
+                                        const gchar        *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_gint32         (FILE               *fd,
+                                        gint32              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 gint32      create_merged_image  (gint32              imageID);
+
+static const Babl* get_pixel_format     (gint32 drawableID);
 
 const GimpPlugInInfo PLUG_IN_INFO =
 {
@@ -235,7 +248,6 @@ query (void)
   gimp_register_save_handler (SAVE_PROC, "psd", "");
 }
 
-
 static void
 run (const gchar      *name,
      gint              nparams,
@@ -412,7 +424,6 @@ psd_lmode_layer (gint32  idLayer,
     }
 }
 
-
 static void
 write_string (FILE        *fd,
               const gchar *val,
@@ -422,7 +433,6 @@ write_string (FILE        *fd,
   xfwrite (fd, val, strlen (val), why);
 }
 
-
 static void
 write_pascalstring (FILE        *fd,
                     const gchar *val,
@@ -460,7 +470,6 @@ write_pascalstring (FILE        *fd,
     write_gchar (fd, 0, why);
 }
 
-
 static void
 xfwrite (FILE          *fd,
          gconstpointer  buf,
@@ -477,7 +486,6 @@ xfwrite (FILE          *fd,
     }
 }
 
-
 static void
 write_gchar (FILE        *fd,
              guchar       val,
@@ -498,7 +506,6 @@ write_gchar (FILE        *fd,
   fseek (fd, pos + 1, SEEK_SET);
 }
 
-
 static void
 write_gint16 (FILE        *fd,
               gint16       val,
@@ -518,9 +525,6 @@ write_gint16 (FILE        *fd,
     }
 }
 
-
-
-
 static void
 write_gint32 (FILE        *fd,
               gint32       val,
@@ -540,7 +544,6 @@ write_gint32 (FILE        *fd,
     }
 }
 
-
 static void
 write_datablock_luni (FILE        *fd,
                       const gchar *val,
@@ -582,7 +585,6 @@ write_datablock_luni (FILE        *fd,
     }
 }
 
-
 static gint32
 pack_pb_line (guchar *start,
               gint32  length,
@@ -667,7 +669,6 @@ gimpBaseTypeToPsdMode (GimpImageBaseType gimpBaseType)
     }
 }
 
-
 static gint
 nChansLayer (gint gimpBaseType,
              gint hasAlpha,
@@ -692,7 +693,6 @@ nChansLayer (gint gimpBaseType,
     }
 }
 
-
 static void
 reshuffle_cmap_write (guchar *mapGimp)
 {
@@ -716,7 +716,6 @@ reshuffle_cmap_write (guchar *mapGimp)
   g_free (mapPSD);
 }
 
-
 static void
 save_header (FILE   *fd,
              gint32  image_id)
@@ -737,13 +736,10 @@ save_header (FILE   *fd,
                 "channels");
   write_gint32 (fd, PSDImageData.image_height, "rows");
   write_gint32 (fd, PSDImageData.image_width, "columns");
-  write_gint16 (fd, 8, "depth");  /* Apparently GIMP only supports 8 bit deep
-                                     PSD images.  */
+  write_gint16 (fd, 8, "depth");  /* Saving can only be done in 8 bits at the moment. */
   write_gint16 (fd, gimpBaseTypeToPsdMode (PSDImageData.baseType), "mode");
 }
 
-
-
 static void
 save_color_mode_data (FILE   *fd,
                       gint32  image_id)
@@ -801,8 +797,6 @@ save_color_mode_data (FILE   *fd,
     }
 }
 
-
-
 static void
 save_resources (FILE   *fd,
                 gint32  image_id)
@@ -1032,8 +1026,6 @@ save_resources (FILE   *fd,
   fseek (fd, eof_pos, SEEK_SET);
 }
 
-
-
 static int
 get_compress_channel_data (guchar  *channel_data,
                            gint32   channel_cols,
@@ -1063,7 +1055,6 @@ get_compress_channel_data (guchar  *channel_data,
   return len;
 }
 
-
 static void
 save_layer_and_mask (FILE   *fd,
                      gint32  image_id)
@@ -1285,32 +1276,26 @@ save_layer_and_mask (FILE   *fd,
   fseek (fd, eof_pos, SEEK_SET);
 }
 
-
-
 static void
 write_pixel_data (FILE   *fd,
                   gint32  drawableID,
                   glong  *ChanLenPosition,
                   gint32  ltable_offset)
 {
-  GimpPixelRgn region;      /* Image region */
-  guchar *data;             /* Temporary copy of pixel data */
-
-  gint32 tile_height = gimp_tile_height();
-
-  GimpDrawable *drawable = gimp_drawable_get (drawableID);
-
-  gint32 height = drawable->height;
-  gint32 width  = drawable->width;
-  gint32 bytes  = drawable->bpp;
-  gint32 colors = bytes;    /* fixed up down below */
-  gint32 y;
-
-  gint32   len;                  /* Length of compressed data */
-  gint16 *LengthsTable;         /* Lengths of every compressed row */
-  guchar *rledata;              /* Compressed data from a region */
-  glong  length_table_pos;      /* position in file of the length table */
-  int i, j;
+  GeglBuffer   *buffer = gimp_drawable_get_buffer (drawableID);
+  const Babl   *format = get_pixel_format (drawableID);
+  gint32        tile_height = gimp_tile_height();
+  gint32        height = gegl_buffer_get_height (buffer);
+  gint32        width  = gegl_buffer_get_width (buffer);
+  gint32        bytes = babl_format_get_bytes_per_pixel (format);
+  gint32        colors = bytes;       /* fixed up down below */
+  gint32        y;
+  gint32        len;                  /* Length of compressed data */
+  gint16       *LengthsTable;         /* Lengths of every compressed row */
+  guchar       *rledata;              /* Compressed data from a region */
+  guchar       *data;                 /* Temporary copy of pixel data */
+  glong         length_table_pos;     /* position in file of the length table */
+  int           i, j;
 
   IFDBG printf (" Function: write_pixel_data, drw %d, lto %d\n",
                 drawableID, ltable_offset);
@@ -1319,17 +1304,12 @@ write_pixel_data (FILE   *fd,
       !gimp_drawable_is_indexed (drawableID))
     colors -= 1;
 
-  gimp_tile_cache_ntiles (2* (drawable->width / gimp_tile_width () + 1));
-
   LengthsTable = g_new (gint16, height);
   rledata = g_new (guchar, (MIN (height, tile_height) *
                             (width + 10 + (width / 100))));
 
   data = g_new (guchar, MIN(height, tile_height) * width * bytes);
 
-  gimp_pixel_rgn_init (&region, drawable, 0, 0,
-                       width, height, FALSE, FALSE);
-
   for (i = 0; i < bytes; i++)
     {
       gint chan;
@@ -1375,8 +1355,8 @@ write_pixel_data (FILE   *fd,
       for (y = 0; y < height; y += tile_height)
         {
           int tlen;
-            gimp_pixel_rgn_get_rect (&region, data, 0, y,
-                                   width, MIN(height - y, tile_height));
+         gegl_buffer_get (buffer, GEGL_RECTANGLE (0, y, width, MIN (height - y, tile_height)),
+                          0, format, data, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
           tlen = get_compress_channel_data (&data[chan],
                                              width,
                                              MIN(height - y, tile_height),
@@ -1410,12 +1390,9 @@ write_pixel_data (FILE   *fd,
 
       if (maskID != -1)
         {
-          GimpDrawable *mdrawable = gimp_drawable_get (maskID);
+          GeglBuffer *mbuffer = gimp_drawable_get_buffer (maskID);
           len = 0;
 
-          gimp_pixel_rgn_init (&region, mdrawable, 0, 0,
-                               width, height, FALSE, FALSE);
-
           if (ChanLenPosition)
             {
               write_gint16 (fd, 1, "Compression type (RLE)");
@@ -1443,8 +1420,8 @@ write_pixel_data (FILE   *fd,
           for (y = 0; y < height; y += tile_height)
             {
               int tlen;
-              gimp_pixel_rgn_get_rect (&region, data, 0, y,
-                                       width, MIN(height - y, tile_height));
+             gegl_buffer_get (mbuffer, GEGL_RECTANGLE (0, y, width, MIN (height - y, tile_height)),
+                              0, format, data, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
               tlen = get_compress_channel_data (&data[0],
                                                 width,
                                                 MIN(height - y, tile_height),
@@ -1474,19 +1451,17 @@ write_pixel_data (FILE   *fd,
           fseek (fd, 0, SEEK_END);
           IF_DEEP_DBG printf ("\t\t\t\t. Cur pos %ld\n", ftell(fd));
 
-          gimp_drawable_detach (mdrawable);
+          g_object_unref (mbuffer);
         }
     }
 
-  gimp_drawable_detach (drawable);
+  g_object_unref (buffer);
 
   g_free (data);
   g_free (rledata);
   g_free (LengthsTable);
 }
 
-
-
 static void
 save_data (FILE   *fd,
            gint32  image_id)
@@ -1542,50 +1517,50 @@ create_merged_image (gint32 image_id)
 
   if (gimp_image_base_type (image_id) != GIMP_INDEXED)
     {
-      GimpDrawable *drawable = gimp_drawable_get (projection);
-      GimpPixelRgn  region;
-      gboolean      transparency_found = FALSE;
-      gpointer      pr;
-
-      gimp_pixel_rgn_init (&region, drawable,
-                           0, 0, drawable->width, drawable->height,
-                           TRUE, FALSE);
-
-      for (pr = gimp_pixel_rgns_register (1, &region);
-           pr != NULL;
-           pr = gimp_pixel_rgns_process (pr))
-        {
-          guchar *data = region.data;
-          gint    y;
+      GeglBuffer           *buffer             = gimp_drawable_get_buffer (projection);
+      const Babl           *format             = get_pixel_format (projection);
+      gboolean              transparency_found = FALSE;
+      gint                  bpp                = babl_format_get_bytes_per_pixel (format);
+      gint                  n_components       = babl_format_get_n_components (format);
+      gint                  width              = gegl_buffer_get_width (buffer);
+      gint                  height             = gegl_buffer_get_height (buffer);
+      GeglBufferIterator   *iter               = gegl_buffer_iterator_new (buffer, GEGL_RECTANGLE (0, 0, 
width, height),
+                                                                          0, format, GEGL_BUFFER_READ, 
GEGL_ABYSS_NONE);
 
-          for (y = 0; y < region.h; y++)
-            {
-              guchar *d = data;
-              gint    x;
+      while (gegl_buffer_iterator_next (iter))
+       {
+         guchar *data = iter->data[0];
+         gint y;
 
-              for (x = 0; x < region.w; x++)
-                {
-                  guint32 alpha = d[region.bpp - 1];
+         for (y = 0; y < iter->roi->height; y++)
+           {
+             guchar *d = data;
+             gint x;
 
-                  if (alpha < 255)
-                    {
-                      gint i;
+             for (x = 0; x < iter->roi->width; x++)
+               {
+                 gint32 alpha = d[bpp - 1];
 
-                      transparency_found = TRUE;
+                 if (alpha < 255)
+                   {
+                     gint i;
 
-                      /* blend against white, photoshop does this. */
-                      for (i = 0; i < region.bpp - 1; i++)
-                        d[i] = ((guint32) d[i] * alpha) / 255 + 255 - alpha;
-                    }
+                     transparency_found = TRUE;
 
-                  d += region.bpp;
-                }
+                     /* blend against white, photoshop does this. */
+                     for (i = 0; i < bpp - 1; i++)
+                       d[i] = ((guint32) d[i] * alpha) / 255 + 255 - alpha;
+                   }
 
-              data += region.rowstride;
-            }
-        }
+               }
+
+              d += bpp;
+           }
+
+         data += n_components;
+       }
 
-      gimp_drawable_detach (drawable);
+      g_object_unref (buffer);
 
       if (! transparency_found)
         gimp_layer_flatten (projection);
@@ -1629,18 +1604,16 @@ get_image_data (FILE   *fd,
   PSDImageData.layersDim = g_new (PSD_Layer_Dimension, PSDImageData.nLayers);
 }
 
-
-
 static gint
 save_image (const gchar  *filename,
             gint32        image_id,
             GError      **error)
 {
-  FILE   *fd;
-  gint32 *layers;
-  gint    nlayers;
-  gint    i;
-  GimpDrawable *drawable;
+  FILE         *fd;
+  gint32       *layers;
+  gint          nlayers;
+  gint          i;
+  GeglBuffer   *buffer;
 
   IFDBG printf (" Function: save_image\n");
 
@@ -1659,8 +1632,8 @@ save_image (const gchar  *filename,
   layers = gimp_image_get_layers (image_id, &nlayers);
   for (i = 0; i < nlayers; i++)
     {
-      drawable = gimp_drawable_get (layers[i]);
-      if (drawable->width > 30000 || drawable->height > 30000)
+      buffer = gimp_drawable_get_buffer (layers[i]);
+      if (gegl_buffer_get_width (buffer) > 30000 || gegl_buffer_get_height (buffer) > 30000)
         {
           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
                        _("Unable to save '%s'.  The PSD file format does not "
@@ -1670,6 +1643,7 @@ save_image (const gchar  *filename,
           g_free (layers);
           return FALSE;
         }
+      g_object_unref (buffer);
     }
   g_free (layers);
 
@@ -1714,3 +1688,36 @@ save_image (const gchar  *filename,
   fclose (fd);
   return TRUE;
 }
+
+static const Babl*
+get_pixel_format (gint32 drawableID)
+{
+  const Babl *format;
+
+  switch (gimp_drawable_type (drawableID))
+    {
+    case GIMP_GRAY_IMAGE:
+      format = babl_format ("Y u8");
+      break;
+
+    case GIMP_GRAYA_IMAGE:
+      format = babl_format ("YA u8");
+      break;
+
+    case GIMP_RGB_IMAGE:
+    case GIMP_INDEXED_IMAGE:
+      format = babl_format ("RGB u8");
+      break;
+
+    case GIMP_RGBA_IMAGE:
+    case GIMP_INDEXEDA_IMAGE:
+      format = babl_format ("RGBA u8");
+      break;
+
+    default:
+      return NULL;
+      break;
+    }
+
+  return format;
+}
diff --git a/plug-ins/file-psd/psd.c b/plug-ins/file-psd/psd.c
index 8fb2674..a7911e6 100644
--- a/plug-ins/file-psd/psd.c
+++ b/plug-ins/file-psd/psd.c
@@ -182,6 +182,7 @@ run (const gchar      *name,
   run_mode = param[0].data.d_int32;
 
   INIT_I18N ();
+  gegl_init (NULL, NULL);
 
   *nreturn_vals = 1;
   *return_vals  = values;
diff --git a/plug-ins/file-psd/psd.h b/plug-ins/file-psd/psd.h
index 1bba60b..f9a6a65 100644
--- a/plug-ins/file-psd/psd.h
+++ b/plug-ins/file-psd/psd.h
@@ -31,7 +31,7 @@
 /* Set to the level of debugging output you want, 0 for none.
  *   Setting higher than 2 will result in a very large amount of debug
  *   output being produced. */
-#define PSD_DEBUG 0
+#define PSD_DEBUG 3
 #define IFDBG(level) if (PSD_DEBUG >= level)
 
 /* Set to FALSE to suppress pop-up warnings about lossy file conversions */
@@ -83,6 +83,8 @@
 #define PSD_LADJ_INVERT         "nvrt"          /* Adjustment layer - invert (PS4) */
 #define PSD_LADJ_THRESHOLD      "thrs"          /* Adjustment layer - threshold (PS4) */
 #define PSD_LADJ_POSTERIZE      "post"          /* Adjustment layer - posterize (PS4) */
+#define PSD_LADJ_VIBRANCE       "vibA"          /* Adjustment layer - vibrance (PS10) */
+#define PSD_LADJ_COLOR_LOOKUP   "clrL"          /* Adjustment layer - color lookup (PS13) */
 
 /* Fill Layer IDs */
 #define PSD_LFIL_SOLID          "SoCo"          /* Solid color sheet setting (PS6) */
@@ -117,12 +119,22 @@
 /* Other */
 #define PSD_LOTH_SECTION        "lsct"          /* Section divider setting - Layer groups (PS6) */
 #define PSD_LOTH_PATTERN        "Patt"          /* Patterns (PS6) */
+#define PSD_LOTH_PATTERN_2      "Pat2"          /* Patterns 2nd key (PS6) */
+#define PSD_LOTH_PATTERN_3      "Pat3"          /* Patterns 3rd key (PS6) */
 #define PSD_LOTH_GRADIENT       "grdm"          /* Gradient settings (PS6) */
 #define PSD_LOTH_RESTRICT       "brst"          /* Channel blending restriction setting (PS6) */
 #define PSD_LOTH_FOREIGN_FX     "ffxi"          /* Foreign effect ID (PS6) */
 #define PSD_LOTH_PATT_DATA      "shpa"          /* Pattern data (PS6) */
 #define PSD_LOTH_META_DATA      "shmd"          /* Meta data setting (PS6) */
 #define PSD_LOTH_LAYER_DATA     "layr"          /* Layer data (PS6) */
+#define PSD_LOTH_CONTENT_GEN    "CgEd"          /* Content generator extra data (PS12) */
+#define PSD_LOTH_TEXT_ENGINE    "Txt2"          /* Text engine data (PS10) */
+#define PSD_LOTH_PATH_NAME      "pths"          /* Unicode path name (PS13) */
+#define PSD_LOTH_ANIMATION_FX   "anFX"          /* Animation effects (PS13) */
+#define PSD_LOTH_FILTER_MASK    "FMsk"          /* Filter mask (PS10) */
+#define PSD_LOTH_VECTOR_STROKE  "vscg"          /* Vector stroke data (PS13) */
+#define PSD_LOTH_ALIGN_RENDER   "sn2P"          /* Aligned rendering flag (?) */
+#define PSD_LOTH_USER_MASK      "LMsk"          /* User mask (?) */
 
 /* Effects layer resource IDs */
 #define PSD_LFX_COMMON          "cmnS"          /* Effects layer - common state (PS5) */
@@ -132,6 +144,24 @@
 #define PSD_LFX_INNER_GLW       "iglw"          /* Effects layer - inner glow (PS5) */
 #define PSD_LFX_BEVEL           "bevl"          /* Effects layer - bevel (PS5) */
 
+/* Placed Layer */
+#define PSD_LPL_PLACE_LAYER     "plLd"          /* Placed layer (?) */
+#define PSD_LPL_PLACE_LAYER_NEW "SoLd"          /* Placed layer (PS10) */
+
+/* Linked Layer */
+#define PSD_LLL_LINKED_LAYER    "lnkD"          /* Linked layer (?) */
+#define PSD_LLL_LINKED_LAYER_2  "lnk2"          /* Linked layer 2nd key */
+#define PSD_LLL_LINKED_LAYER_3  "lnk3"          /* Linked layer 3rd key */
+
+/* Merged Transparency */
+#define PSD_LMT_MERGE_TRANS     "Mtrn"          /* Merged transperency save flag (?) */
+#define PSD_LMT_MERGE_TRANS_16  "Mt16"          /* Merged transperency save flag 2 */
+#define PSD_LMT_MERGE_TRANS_32  "Mt32"          /* Merged transperency save flag 3 */
+
+/* Filter Effects */
+#define PSD_LFFX_FILTER_FX      "FXid"          /* Filter effects (?) */
+#define PSD_LFFX_FILTER_FX_2    "FEid"          /* Filter effects 2 */
+
 /* PSD spec enums */
 
 /* Image color modes */
@@ -169,7 +199,7 @@ typedef enum {
   PSD_PS2_COLOR_TAB     = 1003,         /* 0x03eb - Obsolete - ps 2.0 indexed color table */
   PSD_RESN_INFO         = 1005,         /* 0x03ed - ResolutionInfo structure */
   PSD_ALPHA_NAMES       = 1006,         /* 0x03ee - Alpha channel names */
-  PSD_DISPLAY_INFO      = 1007,         /* 0x03ef - DisplayInfo structure */
+  PSD_DISPLAY_INFO      = 1007,         /* 0x03ef - Superceded by PSD_DISPLAY_INFO_NEW for ps CS3 and higher 
- DisplayInfo structure */
   PSD_CAPTION           = 1008,         /* 0x03f0 - Optional - Caption string */
   PSD_BORDER_INFO       = 1009,         /* 0x03f1 - Border info */
   PSD_BACKGROUND_COL    = 1010,         /* 0x03f2 - Background color */
@@ -198,8 +228,8 @@ typedef enum {
   PSD_COPYRIGHT_FLG     = 1034,         /* 0x040a - Copyright flag */
   PSD_URL               = 1035,         /* 0x040b - URL string */
   PSD_THUMB_RES2        = 1036,         /* 0x040c - Thumbnail resource */
-  PSD_GLOBAL_ANGLE      = 1037,         /* 0x040d - Global angle */
-  PSD_COLOR_SAMPLER     = 1038,         /* 0x040e - Color samplers resource */
+  PSD_GLOBAL_ANGLE      = 1037,         /* 0x040d - Superceded by PSD_NEW_COLOR_SAMPLER for ps CS3 and 
higher - Global angle */
+  PSD_COLOR_SAMPLER     = 1038,         /* 0x040e - Superceded by PSD_NEW_COLOR_SAMPLER for ps CS3 and 
higher - Color samplers resource */
   PSD_ICC_PROFILE       = 1039,         /* 0x040f - ICC Profile */
   PSD_WATERMARK         = 1040,         /* 0x0410 - Watermark */
   PSD_ICC_UNTAGGED      = 1041,         /* 0x0411 - Do not use ICC profile flag */
@@ -216,11 +246,40 @@ typedef enum {
   PSD_ALPHA_ID          = 1053,         /* 0x041d - Alpha IDs */
   PSD_URL_LIST_UNI      = 1054,         /* 0x041e - URL list - unicode */
   PSD_VERSION_INFO      = 1057,         /* 0x0421 - Version info */
-  PSD_EXIF_DATA         = 1058,         /* 0x0422 - Exif data block */
+  PSD_EXIF_DATA         = 1058,         /* 0x0422 - Exif data block 1 */
+  PSD_EXIF_DATA_3       = 1059,         /* 0X0423 - Exif data block 3 (?) */
   PSD_XMP_DATA          = 1060,         /* 0x0424 - XMP data block */
+  PSD_CAPTION_DIGEST    = 1061,         /* 0x0425 - Caption digest */
+  PSD_PRINT_SCALE       = 1062,         /* 0x0426 - Print scale */
+  PSD_PIXEL_AR          = 1064,         /* 0x0428 - Pixel aspect ratio */
+  PSD_LAYER_COMPS       = 1065,         /* 0x0429 - Layer comps */
+  PSD_ALT_DUOTONE_COLOR = 1066,         /* 0x042A - Alternative Duotone colors */
+  PSD_ALT_SPOT_COLOR    = 1067,         /* 0x042B - Alternative Spot colors */
+  PSD_LAYER_SELECT_ID   = 1069,         /* 0x042D - Layer selection ID */
+  PSD_HDR_TONING_INFO   = 1070,         /* 0x042E - HDR toning information */
+  PSD_PRINT_INFO_SCALE  = 1071,         /* 0x042F - Print scale */
+  PSD_LAYER_GROUP_E_ID  = 1072,         /* 0x0430 - Layer group(s) enabled ID */
+  PSD_COLOR_SAMPLER_NEW = 1073,         /* 0x0431 - Color sampler resource for ps CS3 and higher PSD files */
+  PSD_MEASURE_SCALE     = 1074,         /* 0x0432 - Measurement scale */
+  PSD_TIMELINE_INFO     = 1075,         /* 0x0433 - Timeline information */
+  PSD_SHEET_DISCLOSE    = 1076,         /* 0x0434 - Sheet discloser */
+  PSD_DISPLAY_INFO_NEW  = 1077,         /* 0x0435 - DisplayInfo structure for ps CS3 and higher PSD files */
+  PSD_ONION_SKINS       = 1078,         /* 0x0436 - Onion skins */
+  PSD_COUNT_INFO        = 1080,         /* 0x0438 - Count information*/
+  PSD_PRINT_INFO        = 1082,         /* 0x043A - Print information added in ps CS5*/
+  PSD_PRINT_STYLE       = 1083,         /* 0x043B - Print style */
+  PSD_MAC_NSPRINTINFO   = 1084,         /* 0x043C - Mac NSPrintInfo*/
+  PSD_WIN_DEVMODE       = 1085,         /* 0x043D - Windows DEVMODE */
+  PSD_AUTO_SAVE_PATH    = 1086,         /* 0x043E - Auto save file path */
+  PSD_AUTO_SAVE_FORMAT  = 1087,         /* 0x043F - Auto save format */
   PSD_PATH_INFO_FIRST   = 2000,         /* 0x07d0 - First path info block */
   PSD_PATH_INFO_LAST    = 2998,         /* 0x0bb6 - Last path info block */
   PSD_CLIPPING_PATH     = 2999,         /* 0x0bb7 - Name of clipping path */
+  PSD_PLUGIN_R_FIRST    = 4000,         /* 0x0FA0 - First plugin resource */
+  PSD_PLUGIN_R_LAST     = 4999,         /* 0x1387 - Last plugin resource */
+  PSD_IMAGEREADY_VARS   = 7000,         /* 0x1B58 - Imageready variables */
+  PSD_IMAGEREADY_DATA   = 7001,         /* 0x1B59 - Imageready data sets */
+  PSD_LIGHTROOM_WORK    = 8000,         /* 0x1F40 - Lightroom workflow */
   PSD_PRINT_FLAGS_2     = 10000         /* 0x2710 - Print flags */
 } PSDImageResID;
 
@@ -306,7 +365,7 @@ typedef struct
   guint16       red;
   guint16       green;
   guint16       blue;
-}CMRGBColor;
+} CMRGBColor;
 
 /*  HSV Color Value
     A color value expressed in the HSV color space is composed of hue,
@@ -321,7 +380,7 @@ typedef struct
   guint16       hue;
   guint16       saturation;
   guint16       value;
-}CMHSVColor;
+} CMHSVColor;
 
 /* CMYK Color Value
   A color value expressed in the CMYK color space is composed of cyan, magenta,
@@ -336,7 +395,7 @@ typedef struct
   guint16       magenta;
   guint16       yellow;
   guint16       black;
-}CMCMYKColor;
+} CMCMYKColor;
 
 /* L*a*b* Color Value
    The first three values in the color data are, respectively, the colors
@@ -363,17 +422,16 @@ typedef struct
 } CMGrayColor ;
 
 /* The color union is defined by the CMColor type definition.
-*/
+ */
 typedef union
 {
-   CMRGBColor        rgb;
-   CMHSVColor        hsv;
-   CMLabColor        Lab;
-   CMCMYKColor       cmyk;
-   CMGrayColor       gray;
+  CMRGBColor        rgb;
+  CMHSVColor        hsv;
+  CMLabColor        Lab;
+  CMCMYKColor       cmyk;
+  CMGrayColor       gray;
 } CMColor;
 
-
 /* Image resolution data */
 typedef struct {
   Fixed         hRes;                   /* Horizontal resolution pixels/inch */
@@ -410,15 +468,24 @@ typedef struct {
   gint16        planes;                 /* Number of planes (always 1) */
 } ThumbnailInfo;
 
-/* Channel display info data */
+/* Channel display info data for Adobe Photoshop CS2 and lower */
 typedef struct {
-  gint16        colorSpace;             /* Color space from  PSDColorSpace */
+  gint16        colorSpace;             /* Color space from PSDColorSpace */
   guint16       color[4];               /* 4 * 16 bit color components */
   gint16        opacity;                /* Opacity 0 to 100 */
   gchar         kind;                   /* Selected = 0, Protected = 1 */
   gchar         padding;                /* Padding */
 } DisplayInfo;
 
+/* Channel display info data for Adobe Photoshop CS3 and higher to support floating point colors */
+typedef struct {
+  gint16        colorSpace;             /* Color space from PSDColorSpace */
+  guint16       color[4];               /* 4 * 16 bit color components */
+  gint16        opacity;                /* Opacity 0 to 100 */
+  gchar         kind;                   /* Selected = 0, Protected = 1 */
+  gchar         mode;                   /* Alpha = 0, Inverted alpha = 1, Spot = 2 */
+} DisplayInfoNew;
+
 /* PSD Channel length info data structure */
 typedef struct
 {
@@ -444,6 +511,33 @@ typedef struct
   gboolean      invert;                 /* Invert mask on blending */
 } MaskFlags;
 
+/* PSD Slices */
+typedef struct
+{
+  gint32        id;                     /* ID */
+  gint32        groupid;                /* Group ID */
+  gint32        origin;                 /* Origin */
+  gint32        associatedid;           /* Associated Layer ID */
+  gchar         *name;                  /* Name */
+  gint32        type;                   /* Type */
+  gint32        left;                   /* Position coordinates */
+  gint32        top;
+  gint32        right;
+  gint32        bottom;
+  gchar         *url;                   /* URL */
+  gchar         *target;                /* Target */
+  gchar         *message;               /* Message */
+  gchar         *alttag;                /* Alt Tag */
+  gchar         html;                   /* Boolean for if cell text is HTML */
+  gchar         *celltext;              /* Cell text */
+  gint32        horizontal;             /* Horizontal alignment */
+  gint32        vertical;               /* Vertical alignment */
+  gchar         alpha;                  /* Alpha */
+  gchar         red;                    /* Red */
+  gchar         green;                  /* Green */
+  gchar         blue;                   /* Blue */
+} PSDSlice;
+
 /* PSD Layer mask data (length 20) */
 typedef struct
 {
@@ -467,6 +561,18 @@ typedef struct
   gint32                right;                  /* Layer right */
 } LayerMaskExtra;
 
+/* PSD text reading */
+typedef struct
+{
+  gdouble               xx; /* Transform information */
+  gdouble               xy;
+  gdouble               yx;
+  gdouble               yy;
+  gdouble               tx;
+  gdouble               ty;
+  gchar                 *info; /* Text information */
+} PSDText;
+
 /* PSD Layer data structure */
 typedef struct
 {
@@ -489,6 +595,7 @@ typedef struct
   LayerMask             layer_mask;             /* Layer mask data */
   LayerMaskExtra        layer_mask_extra;       /* Layer mask extra data */
   LayerFlags            layer_flags;            /* Layer flags */
+  PSDText               text;                   /* PSD text */
   guint32               id;                     /* Layer ID (Tattoo) */
   guchar                group_type;             /* 0 -> not a group; 1 -> open folder; 2 -> closed folder; 3 
-> end of group */
 } PSDlayer;
@@ -508,6 +615,7 @@ typedef struct
 {
   GimpRGB       gimp_color;             /* Gimp RGB color */
   gint16        opacity;                /* Opacity */
+  guchar        ps_mode;                /* PS mode flag */
   guchar        ps_kind;                /* PS type flag */
   gint16        ps_cspace;              /* PS color space */
   CMColor       ps_color;               /* PS color */
@@ -539,7 +647,7 @@ typedef struct
   gboolean              transparency;           /* Image has merged transparency alpha channel */
   guint32               rows;                   /* Number of rows: 1 - 30000 */
   guint32               columns;                /* Number of columns: 1 - 30000 */
-  guint16               bps;                    /* Bits per channel: 1, 8 or 16 */
+  guint16               bps;                    /* Bits per sample: 1, 8, 16, or 32 */
   guint16               color_mode;             /* Image color mode: {PSDColorMode} */
   GimpImageBaseType     base_type;              /* Image base color mode: (GIMP) */
   guint16               comp_mode;              /* Merged image compression mode */


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