diff --git a/lib/modules/_Image_PSD.pmod b/lib/modules/_Image_PSD.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..53a7b60e494bb8eafce947ad5901a0a5f10656e1
--- /dev/null
+++ b/lib/modules/_Image_PSD.pmod
@@ -0,0 +1,211 @@
+inherit Image._PSD;
+
+class Layer
+{
+  string mode;
+  int opacity;
+  object image;
+  object alpha;
+  
+  int flags;
+  int xoffset, yoffset;
+  int width, height;
+
+
+  Layer copy()
+  {
+    Layer l = Layer();
+    l->mode = mode;
+    l->opacity = opacity;
+    l->image = image;
+    l->alpha = alpha;
+    l->flags = flags;
+    l->xoffset = xoffset;
+    l->yoffset = yoffset;
+    l->width = width;
+    l->height = height;
+    return l;
+  }
+
+
+  Layer get_opaqued( int opaque_value )
+  {
+    Layer res = copy();
+    if(opaque_value != 255)
+    {
+      if(res->alpha)
+        res->alpha *= opaque_value/255.0;
+      else
+        res->alpha = Image.image(width,height,
+                                 opaque_value,opaque_value,opaque_value);
+    }
+    return res;
+  }
+}
+
+Layer decode_layer(mapping layer, mapping i)
+{
+  Layer l = Layer();
+  int use_cmap;
+  l->opacity = layer->opacity;
+  l->width = layer->right-layer->left;
+  l->height = layer->bottom-layer->top;
+  l->xoffset = layer->left;
+  l->yoffset = layer->top;
+  l->image = Image.image( l->width, l->height );
+  l->mode = layer->mode;
+  l->flags = layer->flags;
+
+  array colors;
+  switch(i->mode)
+  {
+   case Greyscale:
+     colors = ({
+       255,255,255
+     })*24;
+     break;
+   case RGB:
+     colors = ({ ({255,0,0,}),
+                 ({0,255,0,}),
+                 ({0,0,255,}),
+               }) + ({ 255,255,255 }) * 24;
+     break;
+   case Indexed:
+     use_cmap = 1;
+     error("Tell per to fix colormap support\n");
+     break;
+   default:
+     werror("Unsupported mode (for now), using greyscale\n");
+     colors = ({
+       255,255,255
+     })*24;
+     break;
+  }
+  foreach(layer->channels, mapping c)
+  {
+    object tmp =___decode_image_channel(l->width,l->height,c->data);
+       
+    switch(c->id)
+    {
+     default:
+       l->image->paste_alpha_color( tmp, @colors[c->id%24] );
+       break;
+     case -1: /* alpha */
+       l->alpha = tmp;
+       break;
+     case -2: /* user mask */
+       if(!l->alpha)
+         l->alpha = tmp;
+       else
+         l->alpha *= tmp;
+       break;
+    }
+  }
+  return l;
+}
+
+mapping __decode( mapping|string what, mapping|void options )
+{
+  mapping data;
+  if(mappingp(what))
+    data = what;
+  else 
+    data = ___decode( what );
+  what=0;
+  array rl = ({});
+  foreach( data->layers, mapping l )
+    rl += ({ decode_layer( l,data ) });
+  data->layers = rl;
+  return data;
+}
+
+#define PASTE_ALPHA(X,Y)                                                \
+        if(Y)                                                           \
+          img->paste_mask( X, Y, l->xoffset, l->yoffset );              \
+        else                                                            \
+          img->paste( X, l->xoffset, l->yoffset );                      \
+        if(Y&&alpha&&++alpha_used)                                      \
+          alpha->paste_alpha_color(Y,255,255,255,l->xoffset, l->yoffset ); \
+        else if(alpha)                                                 \
+         alpha->box(l->xoffset,l->yoffset,l->xoffset+l->width-1,l->yoffset+l->height-1,255,255,255)
+
+#define IMG_SLICE(l,h) img->copy(l->xoffset,l->yoffset,l->xoffset+h->width-1,l->yoffset+h->height-1)
+
+
+array(object) decode_background( mapping data, array bg )
+{
+  object img, alpha;
+  if( !bg )
+    alpha = Image.image(data->width, data->height);
+
+//   if( data->image_data )
+//     img = ___decode_image_data(data->width, data->height, 
+//                                data->channels, data->image_data);
+//   else
+    img = Image.image( data->width, data->height,
+                       @((bg&&(array)bg)||({255,255,255})));
+  return ({ img, alpha });
+}
+
+mapping _decode( string|mapping what, mapping|void opts )
+{
+  mapping data;
+  if(!opts) opts = ([]);
+  if(mappingp(what))
+    data = what;
+  else 
+    data = __decode( what );
+  what=0;
+  object alpha, img;
+  int alpha_used;
+  [img,alpha] = decode_background( data, opts->background );
+
+  foreach(reverse(data->layers), object l)
+  {
+//     if((l->flags & LAYER_FLAG_VISIBLE)|| opts->draw_all_layers)
+    {
+      Layer h = l->get_opaqued( l->opacity );
+
+      switch( l->mode )
+      {
+      case "norm":
+        PASTE_ALPHA(h->image,h->alpha);
+        break;
+
+
+      case "mult":
+        object oi = IMG_SLICE(l,h);
+        oi *= h->image;
+        PASTE_ALPHA(oi,h->alpha);
+        break;
+
+      case "add ":
+        object oi = IMG_SLICE(l,h);
+        oi += h->image;
+        PASTE_ALPHA(oi,h->alpha);
+        break;
+
+      case "diff":
+        object oi = IMG_SLICE(l,h);
+        oi -= h->image;
+        PASTE_ALPHA(oi,h->alpha);
+        break;
+       
+       default:
+        if(!opts->ignore_unknown_layer_modes)
+        {
+          werror("Layer mode "+l->mode+" not yet implemented,  "
+               " asuming 'norm'\n");
+          PASTE_ALPHA(h->image,h->alpha);
+        }
+        break;
+      }
+    }
+  }
+
+  return 
+  ([
+    "image":img,
+    "alpha":alpha,
+  ]);
+}
diff --git a/src/modules/Image/image.c b/src/modules/Image/image.c
index 3bd4a59f60c2a7612f04f26919667608c48d9d72..4b6f988e6fca5ed85e03fc2b25c5bc6a0b4800b3 100644
--- a/src/modules/Image/image.c
+++ b/src/modules/Image/image.c
@@ -1,9 +1,9 @@
-/* $Id: image.c,v 1.128 1999/04/13 12:32:22 mirar Exp $ */
+/* $Id: image.c,v 1.129 1999/04/15 02:40:47 per Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: image.c,v 1.128 1999/04/13 12:32:22 mirar Exp $
+**!	$Id: image.c,v 1.129 1999/04/15 02:40:47 per Exp $
 **! class Image
 **!
 **!	The main object of the <ref>Image</ref> module, this object
@@ -97,7 +97,7 @@
 
 #include "stralloc.h"
 #include "global.h"
-RCSID("$Id: image.c,v 1.128 1999/04/13 12:32:22 mirar Exp $");
+RCSID("$Id: image.c,v 1.129 1999/04/15 02:40:47 per Exp $");
 #include "pike_macros.h"
 #include "object.h"
 #include "constants.h"
@@ -3540,6 +3540,8 @@ extern void exit_image_ilbm(void);
 extern void init_image_ilbm(void);
 extern void init_image_xcf(void);
 extern void exit_image_xcf(void);
+extern void init_image_psd(void);
+extern void exit_image_psd(void);
 extern void init_image_hrz(void);
 extern void exit_image_hrz(void);
 extern void init_image_avs(void);
@@ -3555,6 +3557,7 @@ static struct pike_string
    *magic_XFace,
    *magic_XPM,
    *magic_XCF,
+   *magic_PSD,
    *magic_TIFF,
    *magic_PNG,
    *magic_PS,
@@ -3601,6 +3604,14 @@ static void image_index_magic(INT32 args)
       SAFE_APPLY_MASTER("resolv",2);
       return;
    }
+   else if (sp[-1].u.string==magic_PSD)
+   {
+      pop_stack();
+      push_string(make_shared_string("_Image_PSD"));
+      push_int(0);
+      SAFE_APPLY_MASTER("resolv",2);
+      return;
+   }
    else if (sp[-1].u.string==magic_TIFF)
    {
       pop_stack();
@@ -3650,6 +3661,7 @@ void pike_module_init(void)
    magic_XFace=make_shared_string("XFace");
    magic_XPM=make_shared_string("XPM");
    magic_XCF=make_shared_string("XCF");
+   magic_PSD=make_shared_string("PSD");
    magic_TIFF=make_shared_string("TIFF");
 
    image_noise_init();
@@ -3984,6 +3996,7 @@ void pike_module_init(void)
    init_image__xpm();
    init_image_ilbm();
    init_image_xcf();
+   init_image_psd();
    init_image_x();
    init_image_hrz();
    init_image_avs();
@@ -4011,6 +4024,7 @@ void pike_module_exit(void)
    exit_image_xbm();
    exit_image_ilbm();
    exit_image_xcf();
+   exit_image_psd();
    exit_image_hrz();
    exit_image_avs();
    if (png_object) 
@@ -4026,6 +4040,7 @@ void pike_module_exit(void)
    free_string(magic_XFace);
    free_string(magic_XPM);
    free_string(magic_XCF);
+   free_string(magic_PSD);
    free_string(magic_TIFF);
    free_string(magic_TTF);
    free_string(magic_PS);