diff --git a/lib/modules/_Image_XCF.pmod b/lib/modules/_Image_XCF.pmod
index f5f7506a87af8d36250fa35b63bf3e329643a2c2..5793b44da767e3a6e55e304faaf038ec515e5355 100644
--- a/lib/modules/_Image_XCF.pmod
+++ b/lib/modules/_Image_XCF.pmod
@@ -70,8 +70,8 @@ class Hierarchy
   int height;
   int bpp;
   
-  void create( int x, int y, int bp, array tiles, int compression,
-               Image.colortable cmap)
+  Hierarchy set_image( int x, int y, int bp, array tiles, int compression,
+                       Image.colortable cmap)
   {
     width = x;
     height = y;
@@ -87,18 +87,43 @@ class Hierarchy
      default:
        error("Image tile compression type not supported\n");
     }
+    return this_object();
   }
+
+  Hierarchy qsi(object _i, object _a, int _w, int _h,int _b)
+  {
+    img = _i;
+    alpha = _a;
+    width = _w;
+    height = _h;
+    bpp = _b;
+    return this_object();
+  }
+
+  Hierarchy copy()
+  {
+    return Hierarchy()->qsi( img->copy(),alpha->copy(),width,height,bpp );
+  }
+
+  Hierarchy get_opaqued( int opaque_value )
+  {
+    Hierarchy res = copy();
+    if(opaque_value != 255)
+      res->alpha *= opaque_value/255.0;
+    return res;
+  }
+
 }
 
 int iid;
 Hierarchy decode_image_data( mapping what, object i )
 {
   Hierarchy h = 
-    Hierarchy( what->width, what->height, what->bpp,
-               what->tiles, i->compression, i->colormap );
+    Hierarchy( )->set_image(what->width, what->height, what->bpp,
+                            what->tiles, i->compression, i->colormap );
 
 
-#if 1
+#if 0
   object bg = Image.image( what->width, what->height )->test();
   bg = bg->paste_mask( h->img, h->alpha );
   rm("/tmp/xcftest_"+iid);
@@ -197,9 +222,17 @@ class Layer
        case PROP_SELECTION:
          parent->selection = this_object();
          break;
+       case PROP_OFFSETS:
+         sscanf(p->data, "%4c%4c", xoffset, yoffset);
+         break;
        INT(OPACITY,opacity);
        FLAG(VISIBLE,visible);
-       FLAG(SHOW_MASKED,show_masked);
+       FLAG(LINKED,linked);
+       FLAG(PRESERVE_TRANSPARENCY,preserve_transparency);
+       FLAG(APPLY_MASK,apply_mask);
+       FLAG(EDIT_MASK,edit_mask);
+       FLAG(SHOW_MASK,show_mask);
+       INT(MODE,mode);
        INT(TATTOO,tattoo);
        case PROP_PARASITES:
          parasites = decode_parasites( p->data );
@@ -374,14 +407,63 @@ GimpImage __decode( string|mapping what )
 }
 
 
-mapping _decode( string|mapping what )
+mapping _decode( string|mapping what, mapping|void opts )
 {
+  if(!opts) opts = ([]);
+  mixed e=
+    catch {
   GimpImage data = __decode( what );
-  /* This is rather non-trivial.. */
+  object img = Image.image(data->width, data->height, 
+                           @(opts->background||({255,255,255})));
+  object alpha = Image.image(data->width, data->height,
+                             @(opts->background?({255,255,255}):({0,0,0})));
+
+  foreach(reverse(data->layers), object l)
+  {
+    if(l->flags->visible)
+    {
+      Hierarchy h = l->image->get_opaqued( l->opacity );
+      switch( l->mode )
+      {
+      case NORMAL_MODE:
+        img->paste_mask( h->img, h->alpha, l->xoffset, l->yoffset );
+        alpha->paste_alpha_color( h->alpha, 255,255,255, 
+                                  l->xoffset, l->yoffset );
+        break;
+      case DISSOLVE_MODE:
+      case BEHIND_MODE:
+      case MULTIPLY_MODE:
+      case SCREEN_MODE:
+      case OVERLAY_MODE:
+      case DIFFERENCE_MODE:
+      case ADDITION_MODE:
+      case SUBTRACT_MODE:
+      case DARKEN_ONLY_MODE:
+      case LIGHTEN_ONLY_MODE:
+      case HUE_MODE:
+      case SATURATION_MODE:
+      case COLOR_MODE:
+      case VALUE_MODE:
+      case DIVIDE_MODE:
+      case ERASE_MODE:
+      case REPLACE_MODE:
+        werror("More "+l->mode+" not yet implemented.\n");
+        break;
+      }
+    }
+  }
+
+  return ([
+    "image":img,
+    "alpha":alpha,
+    "gimpimage":data,
+  ]);
+  };
+  werror(describe_backtrace(e));
 }
 
 
-object decode( string what )
+object decode( string what,mapping|void opts )
 {
-  return _decode( what )->image;
+  return _decode( what,opts )->image;
 }
diff --git a/src/modules/Image/encodings/Makefile.in b/src/modules/Image/encodings/Makefile.in
index 3a5f5d2dc1a7c976caa27ed970fb6ddd1434a3a4..e2afbbd41ecd03e491e18719800be96dab5a40eb 100644
--- a/src/modules/Image/encodings/Makefile.in
+++ b/src/modules/Image/encodings/Makefile.in
@@ -1,7 +1,7 @@
-# $Id: Makefile.in,v 1.22 1999/04/06 17:24:29 marcus Exp $
+# $Id: Makefile.in,v 1.23 1999/04/11 07:21:22 per Exp $
 SRCDIR=@srcdir@
 VPATH=@srcdir@:@srcdir@/../../..:../../..
-OBJS = gif.o gif_lzw.o pnm.o x.o xwd.o png.o any.o bmp.o tga.o pcx.o xbm.o _xpm.o ilbm.o iff.o
+OBJS = gif.o gif_lzw.o pnm.o x.o xwd.o png.o any.o bmp.o tga.o pcx.o xbm.o _xpm.o ilbm.o iff.o xcf.o
 
 @SET_MAKE@
 
diff --git a/src/modules/Image/encodings/xcf.c b/src/modules/Image/encodings/xcf.c
index 2e3ba5ef88784951f904c79ba1e72315c8030037..1747721bd0a52da448145f704441724d57b0c132 100644
--- a/src/modules/Image/encodings/xcf.c
+++ b/src/modules/Image/encodings/xcf.c
@@ -1,5 +1,5 @@
 #include "global.h"
-RCSID("$Id: xcf.c,v 1.2 1999/04/11 05:48:51 per Exp $");
+RCSID("$Id: xcf.c,v 1.3 1999/04/11 07:21:23 per Exp $");
 
 #include "config.h"
 
@@ -102,6 +102,29 @@ typedef enum
   INDEXEDA_GIMAGE
 } layer_type;
 
+
+typedef enum {  /*< chop=_MODE >*/
+  NORMAL_MODE,
+  DISSOLVE_MODE,
+  BEHIND_MODE,
+  MULTIPLY_MODE,      /*< nick=MULTIPLY/BURN >*/
+  SCREEN_MODE,
+  OVERLAY_MODE,
+  DIFFERENCE_MODE,
+  ADDITION_MODE,
+  SUBTRACT_MODE,
+  DARKEN_ONLY_MODE,   /*< nick=DARKEN-ONLY >*/
+  LIGHTEN_ONLY_MODE,  /*< nick=LIGHTEN-ONLY >*/
+  HUE_MODE,
+  SATURATION_MODE,
+  COLOR_MODE,
+  VALUE_MODE,
+  DIVIDE_MODE,        /*< nick=DIVIDE/DODGE >*/
+  ERASE_MODE,
+  REPLACE_MODE,
+} LayerModeEffects;
+
+
 typedef enum
 {
   COMPRESS_NONE = 0,
@@ -1214,6 +1237,27 @@ void init_image_xcf()
   add_integer_constant( "COMPRESS_ZLIB", COMPRESS_ZLIB, 0 );
   add_integer_constant( "COMPRESS_FRACTAL", COMPRESS_FRACTAL, 0 );
 
+
+  add_integer_constant("NORMAL_MODE", NORMAL_MODE, 0);
+  add_integer_constant("DISSOLVE_MODE", DISSOLVE_MODE, 0);
+  add_integer_constant("BEHIND_MODE",BEHIND_MODE, 0);
+  add_integer_constant("MULTIPLY_MODE",MULTIPLY_MODE, 0);
+  add_integer_constant("SCREEN_MODE",SCREEN_MODE, 0);
+  add_integer_constant("OVERLAY_MODE",OVERLAY_MODE, 0);
+  add_integer_constant("DIFFERENCE_MODE",DIFFERENCE_MODE, 0);
+  add_integer_constant("ADDITION_MODE",ADDITION_MODE, 0);
+  add_integer_constant("SUBTRACT_MODE",SUBTRACT_MODE, 0);
+  add_integer_constant("DARKEN_ONLY_MODE",DARKEN_ONLY_MODE, 0);
+  add_integer_constant("LIGHTEN_ONLY_MODE",LIGHTEN_ONLY_MODE, 0);
+  add_integer_constant("HUE_MODE",HUE_MODE, 0);
+  add_integer_constant("SATURATION_MODE",SATURATION_MODE, 0);
+  add_integer_constant("COLOR_MODE",COLOR_MODE, 0);
+  add_integer_constant("VALUE_MODE",VALUE_MODE, 0);
+  add_integer_constant("DIVIDE_MODE",DIVIDE_MODE, 0);
+  add_integer_constant("ERASE_MODE",ERASE_MODE, 0);
+  add_integer_constant("REPLACE_MODE",REPLACE_MODE, 0);
+
+
   add_integer_constant( "Red", Red, 0 );
   add_integer_constant( "Green", Green, 0 );
   add_integer_constant( "Blue", Blue, 0 );