diff --git a/lib/modules/_Image_PSD.pmod b/lib/modules/_Image_PSD.pmod
index e1d759596eedad094fa642be824ad8911500ebc9..27eef55a629fd9aed968f834a2e637a1a26c5290 100644
--- a/lib/modules/_Image_PSD.pmod
+++ b/lib/modules/_Image_PSD.pmod
@@ -47,8 +47,10 @@ class Layer
   }
 }
 
+int foo;
 Layer decode_layer(mapping layer, mapping i)
 {
+  int stt = gethrtime();
   Layer l = Layer();
   int use_cmap;
   l->opacity = layer->opacity;
@@ -72,19 +74,50 @@ Layer decode_layer(mapping layer, mapping i)
   }
   array colors;
   int inverted;
+
   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;
+     array lays = ({});
+     foreach( layer->channels, mapping c )
+     {
+       string mode;
+       switch( (int)c->id )
+       {
+        case 0:
+          mode = "red"; 
+          break;
+        case 1:
+          mode = "green"; 
+          break;
+        case 2:
+          mode = "blue"; 
+          break;
+       }
+       if( mode )
+       {
+         int st = gethrtime();
+         if( !sizeof(lays) )
+           lays += ({ 
+             Image.Layer(___decode_image_channel(l->width, l->height,
+                                                 c->data))
+           });
+         else
+           lays += (({ Image.Layer( ([
+             "image":___decode_image_channel(l->width, l->height, c->data),
+             "alpha_value":1.0,
+             "mode":mode, 
+           ]) )
+           }));
+         werror(mode+" took %4.5f seconds\n", (gethrtime()-st)/1000000.0 );
+         c->data = 0;
+       }
+     }
+     int st = gethrtime();
+     l->image = Image.lay( lays )->image();
+     werror("combine took %4.5f seconds\n", (gethrtime()-st)/1000000.0 );
      break;
+
    case CMYK:
      inverted = 1;
      colors = ({ ({255,0,0,}),
@@ -93,23 +126,31 @@ Layer decode_layer(mapping layer, mapping i)
                }) + ({ 255,255,255 }) * 24;
      l->image = Image.image( l->width, l->height, 255, 255, 255);
      break;
+
    case Indexed:
      use_cmap = 1;
      break;
    default:
-     werror("Unsupported mode (for now), using greyscale\n");
-     colors = ({ 255,255,255 })*24;
+     werror("Unsupported layer format mode (for now), using greyscale\n");
+   case Greyscale:
+     colors = ({
+       255,255,255
+     })*24;
      break;
   }
+  int st = gethrtime();
   foreach(layer->channels, mapping c)
   {
     object tmp;
+
+    if( !colors && (c->id >= 0 ))
+      continue;
+
     if( c->id != -2)
       tmp = ___decode_image_channel(l->width, l->height, c->data);
     else
       tmp = ___decode_image_channel(l->mask_width,l->mask_height,c->data);
-
-    switch(c->id)
+    switch( c->id )
     {
      default:
        if(!use_cmap)
@@ -148,7 +189,10 @@ Layer decode_layer(mapping layer, mapping i)
          break;
        }
     }
+    c->data = 0;
   }
+  werror("alpha/mask took %4.5f seconds\n", (gethrtime()-st)/1000000.0 );
+  werror("TOTAL took %4.5f seconds\n\n", (gethrtime()-stt)/1000000.0 );
   return l;
 }
 
@@ -162,95 +206,126 @@ mapping __decode( mapping|string what, mapping|void options )
   what=0;
   array rl = ({});
   foreach( data->layers, mapping l )
-    rl += ({ decode_layer( l,data ) });
+    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);
+  object img;
   if( data->image_data )
     img = ___decode_image_data(data->width,       data->height, 
                                data->channels,    data->mode,
                                data->compression, data->image_data,
                                data->color_data);
-  else
-    img = Image.image( data->width, data->height,
-                       @((bg&&(array)bg)||({255,255,255})));
-  return ({ img, alpha });
+  return ({ img, 0 });
+}
+
+string translate_mode( string mode )
+{
+  switch( mode )
+  {
+   case "norm":      return "normal";
+   case "mul ":      return "multiply";
+   case "add ":      return "add";
+   case "diff":      return "difference";
+   case "sub ":      return "subtract";
+   case "diss":      return "dissolve";
+   case "scrn":      return "screen";
+   case "over":      return "overlay";
+
+
+   case "div ":      return "divide"; //?
+   case "idiv":      return "divide"; //?
+   case "dark":      return "min";
+   case "lite":      return "max";
+
+   case "hue ":      return "hue";
+   case "sat ":      return "saturation";
+   case "colr":      return "color";
+   case "lum ":      return "value";
+
+   case "smud":     
+     werror("WARNING: Unsupported mode (smudge). Skipping layer\n");
+     return 0;
+
+// WARNING: PSD: Unsupported mode: sLit
+// WARNING: PSD: Unsupported mode: hLit
+
+
+   default:
+     werror("WARNING: PSD: Unsupported mode: "+mode+"\n");
+     werror("Skipping layer\n");
+     return 0;
+  }
+}
+
+array decode_layers( string|mapping what, mapping|void opts )
+{
+
+  if(!opts) opts = ([]);
+
+  if(!mappingp( what ) )
+    what = __decode( what );
+  
+  mapping lopts = ([ "tiled":1, ]);
+  if( opts->background )
+  {
+    lopts->image = Image.Image( 32, 32, opts->background );
+    lopts->alpha = Image.Image( 32, 32, Image.Color.white );
+    lopts->alpha_value = 1.0;
+  } else {
+    lopts->image = Image.Image( 32, 32, Image.Color.black );
+    lopts->alpha = Image.Image( 32, 32, Image.Color.black );
+    lopts->alpha_value = 0.0;
+  }
+
+  [object img,object alpha] = decode_background( what, opts->background );
+  if( img )
+  {
+    lopts->image = img;
+    if( alpha )
+      lopts->alpha = alpha;
+    else
+      lopts->alpha = 0;
+    lopts->alpha_value = 1.0;
+  }
+  array layers = ({ Image.Layer( lopts ) });
+
+  foreach(reverse(what->layers), object l)
+  {
+    if( string m = translate_mode( l->mode ) )
+    {
+      Image.Layer lay = Image.Layer( l->image,
+                                   l->alpha,
+                                   m );
+      l->image = 0; l->alpha = 0;
+      lay->set_alpha_value( l->opacity / 255.0 );
+      lay->set_offset( l->xoffset, l->yoffset );
+      layers += ({ lay });
+    }
+  }
+  return layers;
 }
 
 mapping _decode( string|mapping what, mapping|void opts )
 {
+// mixed e = catch{
   mapping data;
-// mixed e =catch{
   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 "mul ":
-        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;
-      }
-    }
-  }
+  Image.Layer res = Image.lay(decode_layers( data, opts ),
+                              0,0,data->width,data->height );
+  Image.Image img = res->image();
+  Image.Image alpha = res->alpha();
 
   return 
   ([
diff --git a/lib/modules/_Image_XCF.pmod b/lib/modules/_Image_XCF.pmod
index 234bbcb84bd27b5de248e615390631fcbc007384..17b7c428b88e8e58010edf7738d64ed4b9e463e6 100644
--- a/lib/modules/_Image_XCF.pmod
+++ b/lib/modules/_Image_XCF.pmod
@@ -430,31 +430,27 @@ string translate_mode( int mode )
   }
 }
 
-mapping _decode( string|mapping what, mapping|void opts )
+array decode_layers( string|object|mapping what, mapping|void opts )
 {
-#ifdef DEBUG
-  mixed e = catch {
-#endif
   if(!opts) opts = ([]);
 
-  GimpImage data = __decode( what );
-  what = 0;
-  array layers = ({});
+  if(!objectp( what ) )
+    what = __decode( what );
   
   mapping lopts = ([ "tiled":1, ]);
   if( opts->background )
   {
     lopts->image = Image.Image( 32, 32, opts->background );
-    lopts->alpha = Image.Image( 32,32, Image.Color.white );
+    lopts->alpha = Image.Image( 32, 32, Image.Color.white );
     lopts->alpha_value = 1.0;
   } else {
     lopts->image = Image.Image( 32, 32, Image.Color.black );
-    lopts->alpha = Image.Image( 32,32, Image.Color.black );
+    lopts->alpha = Image.Image( 32, 32, Image.Color.black );
     lopts->alpha_value = 0.0;
   }
-  layers = ({ Image.Layer( lopts ) });
+  array layers = ({ Image.Layer( lopts ) });
 
-  foreach(data->layers, object l)
+  foreach(what->layers, object l)
   {
     if(l->flags->visible || opts->draw_all_layers)
     {
@@ -484,9 +480,18 @@ mapping _decode( string|mapping what, mapping|void opts )
       layers += ({ lay });
     }
   }
+  return layers;
+}
 
-  Image.Layer res = Image.lay( layers );
-  layers = 0;
+mapping _decode( string|mapping what, mapping|void opts )
+{
+  if(!opts) opts = ([]);
+
+  GimpImage data = __decode( what );
+  what = 0;
+  
+  Image.Layer res = Image.lay(decode_layers( data, opts ),
+                              0,0,data->width,data->height );
   Image.Image img = res->image();
   Image.Image alpha = res->alpha();
   res = 0;
@@ -586,19 +591,12 @@ mapping _decode( string|mapping what, mapping|void opts )
   }
 
   Array.map( data->layers, destruct );
-
   destruct( data );
-
   return 
   ([
     "image":img,
     "alpha":alpha,
   ]);
-#ifdef DEBUG
-  };
-  werror(describe_backtrace( e ) );
-  throw(e);
-#endif
 }