diff --git a/src/modules/image/blit.c b/src/modules/image/blit.c
index f8672fabd626040f3fffe023cbce2f898c3a74bc..d228fcc9887da2f59e4aefe8f343b23a559ca168 100644
--- a/src/modules/image/blit.c
+++ b/src/modules/image/blit.c
@@ -1,4 +1,4 @@
-/* $Id: blit.c,v 1.8 1996/12/05 22:53:23 law Exp $ */
+/* $Id: blit.c,v 1.9 1997/01/07 00:41:40 law Exp $ */
 #include "global.h"
 
 #include <math.h>
@@ -14,6 +14,7 @@
 #include "svalue.h"
 #include "array.h"
 #include "error.h"
+#include "threads.h"
 
 #include "image.h"
 
@@ -56,9 +57,9 @@ static void chrono(char *x)
    ((unsigned char)((y*(255L-(alpha))+x*(alpha))/255L))
 
 #define set_rgb_group_alpha(dest,src,alpha) \
-   ((dest).r=apply_alpha((dest).r,(src).r,alpha), \
-    (dest).g=apply_alpha((dest).g,(src).g,alpha), \
-    (dest).b=apply_alpha((dest).b,(src).b,alpha))
+   (((dest).r=apply_alpha((dest).r,(src).r,alpha)), \
+    ((dest).g=apply_alpha((dest).g,(src).g,alpha)), \
+    ((dest).b=apply_alpha((dest).b,(src).b,alpha)))
 
 #define pixel(_img,x,y) ((_img)->img[(x)+(y)*(_img)->xsize])
 
@@ -96,24 +97,32 @@ static INLINE void getrgb(struct image *img,
 
 void img_clear(rgb_group *dest,rgb_group rgb,INT32 size)
 {
+   THREADS_ALLOW();
    while (size--) *(dest++)=rgb;
+   THREADS_DISALLOW();
 }
 
 void img_box_nocheck(INT32 x1,INT32 y1,INT32 x2,INT32 y2)
 {
    INT32 x,mod;
    rgb_group *foo,*end,rgb;
+   struct image *this;
 
-   mod=THIS->xsize-(x2-x1)-1;
-   foo=THIS->img+x1+y1*THIS->xsize;
-   end=THIS->img+x1+y2*THIS->xsize;
-   rgb=THIS->rgb;
+   this=THIS;
+   
+   THREADS_ALLOW();
+   mod=this->xsize-(x2-x1)-1;
+   foo=this->img+x1+y1*this->xsize;
+   end=this->img+x1+y2*this->xsize;
+   rgb=this->rgb;
 
-   if (!THIS->alpha)
+
+   if (!this->alpha)
       for (; foo<=end; foo+=mod) for (x=x1; x<=x2; x++) *(foo++)=rgb;
    else
       for (; foo<=end; foo+=mod) for (x=x1; x<=x2; x++,foo++) 
-	 set_rgb_group_alpha(*foo,rgb,THIS->alpha);
+	 set_rgb_group_alpha(*foo,rgb,this->alpha);
+   THREADS_DISALLOW();
 }
 
 
@@ -122,12 +131,14 @@ void img_blit(rgb_group *dest,rgb_group *src,INT32 width,
 {
 CHRONO("image_blit begin");
 
+   THREADS_ALLOW();
    while (lines--)
    {
       MEMCPY(dest,src,sizeof(rgb_group)*width);
       dest+=moddest;
       src+=modsrc;
    }
+   THREADS_DISALLOW();
 CHRONO("image_blit end");
 
 }
@@ -152,7 +163,9 @@ void img_crop(struct image *dest,
       new=malloc( (x2-x1+1)*(y2-y1+1)*sizeof(rgb_group) + 1);
       if (!new) 
 	error("Out of memory.\n");
+      THREADS_ALLOW();
       MEMCPY(new,img->img,(x2-x1+1)*(y2-y1+1)*sizeof(rgb_group));
+      THREADS_DISALLOW();
       dest->img=new;
       return;
    }
@@ -191,7 +204,9 @@ void img_clone(struct image *newimg,struct image *img)
    if (newimg->img) free(newimg->img);
    newimg->img=malloc(sizeof(rgb_group)*img->xsize*img->ysize +1);
    if (!newimg->img) error("Out of memory!\n");
+   THREADS_ALLOW();
    MEMCPY(newimg->img,img->img,sizeof(rgb_group)*img->xsize*img->ysize);
+   THREADS_DISALLOW();
    newimg->xsize=img->xsize;
    newimg->ysize=img->ysize;
    newimg->rgb=img->rgb;
@@ -267,6 +282,8 @@ void image_paste_alpha(INT32 args)
    }
    else x1=y1=0;
 
+/* tr�da h�r n�ndag */
+
    for (x=0; x<img->xsize; x++)
       for (y=0; y<img->ysize; y++)
       {
@@ -330,6 +347,7 @@ CHRONO("image_paste_mask begin");
 
    q=1.0/255;
 
+   THREADS_ALLOW();
    for (y=max(0,-y1); y<y2; y++)
    {
       for (x=max(0,-x1); x<x2; x++)
@@ -347,6 +365,7 @@ CHRONO("image_paste_mask begin");
       }
       s+=smod; m+=mmod; d+=dmod;
    }
+   THREADS_DISALLOW();
 CHRONO("image_paste_mask end");
 
    pop_n_elems(args);
@@ -408,6 +427,7 @@ CHRONO("image_paste_alpha_color begin");
 
    rgb=THIS->rgb;
 
+   THREADS_ALLOW();
    for (y=max(0,-y1); y<y2; y++)
    {
       for (x=max(0,-x1); x<x2; x++)
@@ -425,6 +445,7 @@ CHRONO("image_paste_alpha_color begin");
       }
       m+=mmod; d+=dmod;
    }
+   THREADS_DISALLOW();
 CHRONO("image_paste_alpha_color end");
 
    pop_n_elems(args);
diff --git a/src/modules/image/image.c b/src/modules/image/image.c
index d2c0d95e84380e686e24021212d86ca8e009f6c6..5da4726dee851ecadef166a63cc001d7fea900e9 100644
--- a/src/modules/image/image.c
+++ b/src/modules/image/image.c
@@ -1,4 +1,4 @@
-/* $Id: image.c,v 1.35 1996/12/13 03:22:08 law Exp $ */
+/* $Id: image.c,v 1.36 1997/01/07 00:41:41 law Exp $ */
 
 #include "global.h"
 
@@ -7,13 +7,14 @@
 
 #include "stralloc.h"
 #include "global.h"
-RCSID("$Id: image.c,v 1.35 1996/12/13 03:22:08 law Exp $");
+RCSID("$Id: image.c,v 1.36 1997/01/07 00:41:41 law Exp $");
 #include "types.h"
 #include "macros.h"
 #include "object.h"
 #include "constants.h"
 #include "interpret.h"
 #include "svalue.h"
+#include "threads.h"
 #include "array.h"
 #include "error.h"
 
@@ -38,6 +39,33 @@ static INT32 circle_sin_table[CIRCLE_STEPS];
 #define circle_sin_mul(x,y) ((circle_sin(x)*(y))/4096)
 #define circle_cos_mul(x,y) ((circle_cos(x)*(y))/4096)
 
+
+
+#if 1
+#include <sys/resource.h>
+#define CHRONO(X) chrono(X)
+
+static void chrono(char *x)
+{
+   struct rusage r;
+   static struct rusage rold;
+   getrusage(RUSAGE_SELF,&r);
+   fprintf(stderr,"%s: %ld.%06ld - %ld.%06ld\n",x,
+	   r.ru_utime.tv_sec,r.ru_utime.tv_usec,
+
+	   ((r.ru_utime.tv_usec-rold.ru_utime.tv_usec<0)?-1:0)
+	   +r.ru_utime.tv_sec-rold.ru_utime.tv_sec,
+           ((r.ru_utime.tv_usec-rold.ru_utime.tv_usec<0)?1000000:0)
+           + r.ru_utime.tv_usec-rold.ru_utime.tv_usec
+	   );
+
+   rold=r;
+}
+#else
+#define CHRONO(X)
+#endif
+
+
 /***************** init & exit *********************************/
 
 static int obj_counter=0;
@@ -168,7 +196,7 @@ static INLINE rgb_group _pixel_apply_matrix(struct image *img,
 					    int width,int height,
 					    rgbd_group *matrix,
 					    rgb_group default_rgb,
-					    INT32 div)
+					    double div)
 {
    rgb_group res;
    int i,j,bx,by,xp,yp;
@@ -217,11 +245,16 @@ void img_apply_matrix(struct image *dest,
 		      int width,int height,
 		      rgbd_group *matrix,
 		      rgb_group default_rgb,
-		      INT32 div)
+		      double div)
 {
-   rgb_group *d;
+   rgb_group *d,*ip,*dp;
+   rgbd_group *mp;
    int i,j,x,y,bx,by,ex,ey,xp,yp;
    int sumr,sumg,sumb;
+   double qr,qg,qb;
+   register double r=0,g=0,b=0;
+
+THREADS_ALLOW();
 
    sumr=sumg=sumb=0;
    for (i=0; i<width; i++)
@@ -232,9 +265,9 @@ void img_apply_matrix(struct image *dest,
 	 sumb+=matrix[i+j*width].b;
       }
 
-   if (!sumr) sumr=1; sumr*=div;
-   if (!sumg) sumg=1; sumg*=div;
-   if (!sumb) sumb=1; sumb*=div;
+   if (!sumr) sumr=1; sumr*=div; qr=1.0/sumr;
+   if (!sumg) sumg=1; sumg*=div; qg=1.0/sumg;
+   if (!sumb) sumb=1; sumb*=div; qb=1.0/sumb;
 
    bx=width/2;
    by=height/2;
@@ -245,17 +278,23 @@ void img_apply_matrix(struct image *dest,
 
    if(!d) error("Out of memory.\n");
    
-   for (x=bx; x<img->xsize-ex; x++)
+CHRONO("apply_matrix, one");
+
+   for (y=by; y<img->ysize-ey; y++)
    {
-      for (y=by; y<img->ysize-ey; y++)
+      dp=d+y*img->xsize+by;
+      for (x=bx; x<img->xsize-ex; x++)
       {
-	 long r=0,g=0,b=0;
-	 for (xp=x-bx,i=0; i<width; i++,xp++)
-	    for (yp=y-by,j=0; j<height; j++,yp++)
+	 r=g=b=0;
+	 mp=matrix;
+	 for (yp=y-by,j=0; j<height; j++,yp++)
+	 {
+	    ip=img->img+(x-bx)+yp*img->xsize;
+	    for (i=0; i<width; i++)
 	    {
-	       r+=matrix[i+j*width].r*img->img[xp+yp*img->xsize].r;
-	       g+=matrix[i+j*width].g*img->img[xp+yp*img->xsize].g;
-	       b+=matrix[i+j*width].b*img->img[xp+yp*img->xsize].b;
+	       r+=ip->r*mp->r;
+ 	       g+=ip->g*mp->g;
+ 	       b+=ip->b*mp->b;
 #ifdef MATRIX_DEBUG
 	       fprintf(stderr,"%d,%d ->%d,%d,%d\n",
 		       i,j,
@@ -263,16 +302,21 @@ void img_apply_matrix(struct image *dest,
 		       img->img[x+i+(y+j)*img->xsize].g,
 		       img->img[x+i+(y+j)*img->xsize].b);
 #endif
+	       mp++;
+	       ip++;
 	    }
+	 }
 #ifdef MATRIX_DEBUG
 	 fprintf(stderr,"->%d,%d,%d\n",r/sumr,g/sumg,b/sumb);
 #endif
-	 d[x+y*img->xsize].r=testrange(default_rgb.r+r/sumr);
-	 d[x+y*img->xsize].g=testrange(default_rgb.g+g/sumg);
-	 d[x+y*img->xsize].b=testrange(default_rgb.b+b/sumb);
+	 r=default_rgb.r+(int)(r*qr+0.5); dp->r=testrange(r);
+	 g=default_rgb.g+(int)(g*qg+0.5); dp->g=testrange(g);
+	 b=default_rgb.b+(int)(b*qb+0.5); dp->b=testrange(b);
+	 dp++;
       }
    }
 
+CHRONO("apply_matrix, two");
 
    for (y=0; y<img->ysize; y++)
    {
@@ -294,9 +338,13 @@ void img_apply_matrix(struct image *dest,
 					       matrix,default_rgb,div);
    }
 
+CHRONO("apply_matrix, three");
+
    if (dest->img) free(dest->img);
    *dest=*img;
    dest->img=d;
+
+THREADS_DISALLOW();
 }
 
 /***************** methods *************************************/
@@ -748,6 +796,7 @@ void image_tuned_box(INT32 args)
    INT32 x1,y1,x2,y2,xw,yw,x,y;
    rgba_group topleft,topright,bottomleft,bottomright,sum,sumzero={0,0,0,0};
    rgb_group *img;
+   struct image *this;
 
    if (args<5||
        sp[-args].type!=T_INT||
@@ -781,6 +830,10 @@ void image_tuned_box(INT32 args)
 
    xw=x2-x1;
    yw=y2-y1;
+
+   this=THIS;
+   THREADS_ALLOW();
+
    for (x=max(0,-x1); x<=xw && x+x1<THIS->xsize; x++)
    {
 #define tune_factor(a,aw) (1.0-((float)(a)/(aw)))
@@ -788,8 +841,8 @@ void image_tuned_box(INT32 args)
       float tfx1=tune_factor(x,xw);
       float tfx2=tune_factor(xw-x,xw);
 
-      ymax=min(yw,THIS->ysize-y1);
-      img=THIS->img+x+x1+THIS->xsize*max(0,y1);
+      ymax=min(yw,this->ysize-y1);
+      img=this->img+x+x1+this->xsize*max(0,y1);
       if (topleft.alpha||topright.alpha||bottomleft.alpha||bottomright.alpha)
 	 for (y=max(0,-y1); y<ymax; y++)
 	 {
@@ -802,7 +855,7 @@ void image_tuned_box(INT32 args)
 	    add_to_rgba_sum_with_factor(&sum,bottomright,tfy*tfx2);
 
 	    set_rgb_group_alpha(*img, sum,sum.alpha);
-	    img+=THIS->xsize;
+	    img+=this->xsize;
 	 }
       else
 	 for (y=max(0,-y1); y<ymax; y++)
@@ -816,10 +869,11 @@ void image_tuned_box(INT32 args)
 	    add_to_rgb_sum_with_factor(&sum,bottomright,tfy*tfx2);
 
 	    *img=sum;
-	    img+=THIS->xsize;
+	    img+=this->xsize;
 	 }
 	 
    }
+   THREADS_DISALLOW();
 
    pop_n_elems(args);
    THISOBJ->refs++;
@@ -867,16 +921,18 @@ void image_gray(INT32 args)
 
    d=img->img;
    s=THIS->img;
-   for (x=0; x<THIS->xsize; x++)
-      for (y=0; y<THIS->ysize; y++)
-      {
-	 d->r=d->g=d->b=
-	    testrange( ((((long)s->r)*rgb.r+
-			 ((long)s->g)*rgb.g+
-			 ((long)s->b)*rgb.b)/div) );
-	 d++;
-	 s++;
-      }
+   x=THIS->xsize*THIS->ysize;
+   THREADS_ALLOW();
+   while (x--)
+   {
+      d->r=d->g=d->b=
+	 testrange( ((((long)s->r)*rgb.r+
+		      ((long)s->g)*rgb.g+
+		      ((long)s->b)*rgb.b)/div) );
+      d++;
+      s++;
+   }
+   THREADS_DISALLOW();
    pop_n_elems(args);
    push_object(o);
 }
@@ -913,15 +969,19 @@ void image_color(INT32 args)
 
    d=img->img;
    s=THIS->img;
-   for (x=0; x<THIS->xsize; x++)
-      for (y=0; y<THIS->ysize; y++)
-      {
-	 d->r=testrange( (((long)rgb.r*s->r)/255) );
-	 d->g=testrange( (((long)rgb.g*s->g)/255) );
-	 d->b=testrange( (((long)rgb.b*s->b)/255) );
-	 d++;
-	 s++;
-      }
+
+   x=THIS->xsize*THIS->ysize;
+
+   THREADS_ALLOW();
+   while (x--)
+   {
+      d->r=testrange( (((long)rgb.r*s->r)/255) );
+      d->g=testrange( (((long)rgb.g*s->g)/255) );
+      d->b=testrange( (((long)rgb.b*s->b)/255) );
+      d++;
+      s++;
+   }
+   THREADS_DISALLOW();
 
    pop_n_elems(args);
    push_object(o);
@@ -948,15 +1008,17 @@ void image_invert(INT32 args)
    d=img->img;
    s=THIS->img;
 
-   for (x=0; x<THIS->xsize; x++)
-      for (y=0; y<THIS->ysize; y++)
-      {
-	 d->r=testrange( 255-s->r );
-	 d->g=testrange( 255-s->g );
-	 d->b=testrange( 255-s->b );
-	 d++;
-	 s++;
-      }
+   x=THIS->xsize*THIS->ysize;
+   THREADS_ALLOW();
+   while (x--)
+   {
+      d->r=testrange( 255-s->r );
+      d->g=testrange( 255-s->g );
+      d->b=testrange( 255-s->b );
+      d++;
+      s++;
+   }
+   THREADS_DISALLOW();
 
    pop_n_elems(args);
    push_object(o);
@@ -965,7 +1027,7 @@ void image_invert(INT32 args)
 void image_threshold(INT32 args)
 {
    INT32 x,y;
-   rgb_group *s,*d;
+   rgb_group *s,*d,rgb;
    struct object *o;
    struct image *img;
 
@@ -984,20 +1046,23 @@ void image_threshold(INT32 args)
 
    d=img->img;
    s=THIS->img;
+   rgb=THIS->rgb;
 
-   for (x=0; x<THIS->xsize; x++)
-      for (y=0; y<THIS->ysize; y++)
-      {
-	 if (s->r>=THIS->rgb.r &&
-	     s->g>=THIS->rgb.g &&
-	     s->b>=THIS->rgb.b)
-   	    d->r=d->g=d->b=255;
-	 else
-            d->r=d->g=d->b=0;
+   x=THIS->xsize*THIS->ysize;
+   THREADS_ALLOW();
+   while (x--)
+   {
+      if (s->r>=rgb.r &&
+	  s->g>=rgb.g &&
+	  s->b>=rgb.b)
+	 d->r=d->g=d->b=255;
+      else
+	 d->r=d->g=d->b=0;
 
-	 d++;
-	 s++;
-      }
+      d++;
+      s++;
+   }
+   THREADS_DISALLOW();
 
    pop_n_elems(args);
    push_object(o);
@@ -1027,6 +1092,7 @@ void image_distancesq(INT32 args)
    s=THIS->img;
    rgb=THIS->rgb;
 
+   THREADS_ALLOW();
    i=img->xsize*img->ysize;
    while (i--)
    {
@@ -1035,6 +1101,7 @@ void image_distancesq(INT32 args)
       d->r=d->g=d->b=testrange(DISTANCE(*s,rgb)>>8);
       d++; s++;
    }
+   THREADS_DISALLOW();
 
    pop_n_elems(args);
    push_object(o);
@@ -1202,7 +1269,9 @@ void image_apply_matrix(INT32 args)
    rgbd_group *matrix;
    rgb_group default_rgb;
    struct object *o;
-   INT32 div;
+   double div;
+
+CHRONO("apply_matrix");
 
    if (args<1 ||
        sp[-args].type!=T_ARRAY)
@@ -1225,14 +1294,20 @@ void image_apply_matrix(INT32 args)
       default_rgb.g=0;
       default_rgb.b=0;
    }
+
    if (args>4 
        && sp[4-args].type==T_INT)
    {
       div=sp[4-args].u.integer;
       if (!div) div=1;
    }
-   else
-      div=1;
+   else if (args>4 
+	    && sp[4-args].type==T_FLOAT)
+   {
+      div=sp[4-args].u.float_number;
+      if (!div) div=1;
+   }
+   else div=1;
    
    height=sp[-args].u.array->size;
    width=-1;
@@ -1290,10 +1365,14 @@ void image_apply_matrix(INT32 args)
 
    o=clone(image_program,0);
 
+CHRONO("apply_matrix, begin");
+
    if (THIS->img)
       img_apply_matrix((struct image*)o->storage,THIS,
 		       width,height,matrix,default_rgb,div);
 
+CHRONO("apply_matrix, end");
+
    free(matrix);
 
    pop_n_elems(args);
@@ -1376,16 +1455,20 @@ void image_modify_by_intensity(INT32 args)
 
    d=img->img;
    s=THIS->img;
-   for (x=0; x<THIS->xsize; x++)
-      for (y=0; y<THIS->ysize; y++)
-      {
-	 i= testrange( ((((long)s->r)*rgb.r+
-			 ((long)s->g)*rgb.g+
-			 ((long)s->b)*rgb.b)/div) );
-	 *d=list[i];
-	 d++;
-	 s++;
-      }
+
+
+   x=THIS->xsize*THIS->ysize;
+   THREADS_ALLOW();
+   while (x--)
+   {
+      i= testrange( ((((long)s->r)*rgb.r+
+		      ((long)s->g)*rgb.g+
+		      ((long)s->b)*rgb.b)/div) );
+      *d=list[i];
+      d++;
+      s++;
+   }
+   THREADS_DISALLOW();
 
    free(list);
 
@@ -1415,11 +1498,13 @@ static void image_map_closest(INT32 args)
    i=THIS->xsize*THIS->ysize;
    s=THIS->img;
    d=((struct image*)(o->storage))->img;
+   THREADS_ALLOW();
    while (i--)
    {
       *d=ct->clut[colortable_rgb_nearest(ct,*s)];
       d++; *s++;
    }
+   THREADS_DISALLOW();
 
    colortable_free(ct);
    push_object(o);
@@ -1447,11 +1532,13 @@ static void image_map_fast(INT32 args)
    i=THIS->xsize*THIS->ysize;
    s=THIS->img;
    d=((struct image*)(o->storage))->img;
+   THREADS_ALLOW();
    while (i--)
    {
       *d=ct->clut[colortable_rgb(ct,*s)];
       d++; *s++;
    }
+   THREADS_DISALLOW();
 
    colortable_free(ct);
    push_object(o);
@@ -1460,7 +1547,7 @@ static void image_map_fast(INT32 args)
 static void image_map_fs(INT32 args)
 {
    struct colortable *ct;
-   INT32 i,j;
+   INT32 i,j,xs;
    rgb_group *d,*s;
    struct object *o;
    int *res,w;
@@ -1490,13 +1577,16 @@ static void image_map_fs(INT32 args)
    s=THIS->img;
    d=((struct image*)(o->storage))->img;
    w=0;
+   xs=THIS->xsize;
+   THREADS_ALLOW();
    while (i--)
    {
-      image_floyd_steinberg(s,THIS->xsize,errb,w=!w,res,ct);
+      image_floyd_steinberg(s,xs,errb,w=!w,res,ct);
       for (j=0; j<THIS->xsize; j++)
 	 *(d++)=ct->clut[res[j]];
-      s+=THIS->xsize;
+      s+=xs;
    }
+   THREADS_DISALLOW();
 
    free(errb);
    free(res);
diff --git a/src/modules/image/lzw.c b/src/modules/image/lzw.c
index 5c34c8cb37fe2f6779d6a0cf032d419a6f306741..f53905f721cf31423b9233246d7501ae77a806f1 100644
--- a/src/modules/image/lzw.c
+++ b/src/modules/image/lzw.c
@@ -1,4 +1,4 @@
-/* $Id: lzw.c,v 1.8 1996/11/22 20:28:17 law Exp $ */
+/* $Id: lzw.c,v 1.9 1997/01/07 00:41:42 law Exp $ */
 
 /*
 
@@ -21,7 +21,54 @@ the existanse of #define GIF_LZW is for that purpose. :-)
 #define STDLZWCODES 8192
 #endif
 
-static void lzw_output(struct lzw *lzw,lzwcode_t codeno);
+static INLINE void lzw_output(struct lzw *lzw,lzwcode_t codeno)
+{
+   int bits,bitp;
+   unsigned char c;
+
+/*
+   fprintf(stderr,"%03x bits=%d codes %d %c\n",
+           codeno,lzw->codebits,lzw->codes+1,
+	   (codeno==lzw->codes+1) ? '=' : ' ');
+	   */
+#if 0
+   fprintf(stderr,"\nwrote %4d<'",codeno);
+   lzw_recurse_find_code(lzw,codeno);
+   fprintf(stderr,"' ");
+#endif
+
+   if (lzw->outpos+4>=lzw->outlen)
+      lzw->out=realloc(lzw->out,lzw->outlen*=2);
+
+   bitp=lzw->outbit;
+   c=lzw->lastout;
+   bits=lzw->codebits;
+#ifdef GIF_LZW
+   if (bits>12) bits=12;
+#endif
+
+   while (bits)
+   {
+      c|=(codeno<<bitp);
+      if (bits+bitp>=8)
+      {
+	 bits-=8-bitp;
+	 codeno>>=8-bitp;
+	 bitp=0;
+	 lzw->out[lzw->outpos++]=c;
+	 c=0;
+      }
+      else
+      {
+	 lzw->outbit=bitp+bits;
+	 lzw->lastout=c;
+	 return;
+      }
+   }
+   lzw->lastout=0;
+   lzw->outbit=0;
+}
+
 
 void lzw_init(struct lzw *lzw,int bits)
 {
@@ -92,54 +139,6 @@ static void lzw_recurse_find_code(struct lzw *lzw,lzwcode_t codeno)
 }
 #endif
 
-static INLINE void lzw_output(struct lzw *lzw,lzwcode_t codeno)
-{
-   int bits,bitp;
-   unsigned char c;
-
-/*
-   fprintf(stderr,"%03x bits=%d codes %d %c\n",
-           codeno,lzw->codebits,lzw->codes+1,
-	   (codeno==lzw->codes+1) ? '=' : ' ');
-	   */
-#if 0
-   fprintf(stderr,"\nwrote %4d<'",codeno);
-   lzw_recurse_find_code(lzw,codeno);
-   fprintf(stderr,"' ");
-#endif
-
-   if (lzw->outpos+4>=lzw->outlen)
-      lzw->out=realloc(lzw->out,lzw->outlen*=2);
-
-   bitp=lzw->outbit;
-   c=lzw->lastout;
-   bits=lzw->codebits;
-#ifdef GIF_LZW
-   if (bits>12) bits=12;
-#endif
-
-   while (bits)
-   {
-      c|=(codeno<<bitp);
-      if (bits+bitp>=8)
-      {
-	 bits-=8-bitp;
-	 codeno>>=8-bitp;
-	 bitp=0;
-	 lzw->out[lzw->outpos++]=c;
-	 c=0;
-      }
-      else
-      {
-	 lzw->outbit=bitp+bits;
-	 lzw->lastout=c;
-	 return;
-      }
-   }
-   lzw->lastout=0;
-   lzw->outbit=0;
-}
-
 void lzw_write_last(struct lzw *lzw)
 {
    if (lzw->current)
diff --git a/src/modules/image/matrix.c b/src/modules/image/matrix.c
index 54c90ac0bd08426adf9af0d2ead42e47af89dae5..fd738e25db89cf338c14984de3bc06fb814f6b0a 100644
--- a/src/modules/image/matrix.c
+++ b/src/modules/image/matrix.c
@@ -1,4 +1,4 @@
-/* $Id: matrix.c,v 1.8 1996/12/05 23:50:53 law Exp $ */
+/* $Id: matrix.c,v 1.9 1997/01/07 00:41:43 law Exp $ */
 
 #include "global.h"
 
@@ -14,6 +14,7 @@
 #include "interpret.h"
 #include "svalue.h"
 #include "array.h"
+#include "threads.h"
 #include "error.h"
 
 #include "image.h"
@@ -156,6 +157,7 @@ void img_scale(struct image *dest,
    INT32 y,yd;
    double yn,dx,dy;
 
+   THREADS_ALLOW();
 CHRONO("scale begin");
 
    if (dest->img) { free(dest->img); dest->img=NULL; }
@@ -211,6 +213,7 @@ CHRONO("transfer begin");
    free(new);
 
 CHRONO("scale end");
+   THREADS_DISALLOW();
 }
 
 /* Special, faster, case for scale=1/2 */
@@ -221,6 +224,7 @@ void img_scale2(struct image *dest, struct image *source)
    newx = source->xsize >> 1;
    newy = source->ysize >> 1;
    
+   THREADS_ALLOW();
    if (dest->img) { free(dest->img); dest->img=NULL; }
    if (!THIS->img || newx<=0 || newy<=0) return; /* no way */
    new=malloc(newx*newy*sizeof(rgb_group) +1);
@@ -248,6 +252,7 @@ void img_scale2(struct image *dest, struct image *source)
 			      (INT32) pixel(source,2*x+0,2*y+1).b+
 			      (INT32) pixel(source,2*x+1,2*y+1).b) >> 2);
      }
+   THREADS_DISALLOW();
 }
 
 
@@ -310,7 +315,7 @@ void image_scale(INT32 args)
 
 void image_ccw(INT32 args)
 {
-   INT32 i,j;
+   INT32 i,j,xs,ys;
    rgb_group *src,*dest;
    struct object *o;
    struct image *img;
@@ -329,16 +334,20 @@ void image_ccw(INT32 args)
    }
    img->xsize=THIS->ysize;
    img->ysize=THIS->xsize;
-   i=THIS->xsize;
+   i=xs=THIS->xsize;
+   ys=THIS->ysize;
    src=THIS->img+THIS->xsize-1;
    dest=img->img;
+
+   THREADS_ALLOW();
    while (i--)
    {
-      j=THIS->ysize;
-      while (j--) *(dest++)=*(src),src+=THIS->xsize;
+      j=ys;
+      while (j--) *(dest++)=*(src),src+=xs;
       src--;
-      src-=THIS->xsize*THIS->ysize;
+      src-=xs*ys;
    }
+   THREADS_DISALLOW();
 
    push_object(o);
 }
@@ -358,6 +367,7 @@ static void img_cw(struct image *is,struct image *id)
    i=is->xsize;
    src=is->img+is->xsize-1;
    dest=id->img;
+   THREADS_ALLOW();
    while (i--)
    {
       j=is->ysize;
@@ -365,6 +375,7 @@ static void img_cw(struct image *is,struct image *id)
       src--;
       src-=is->xsize*is->ysize;
    }
+   THREADS_DISALLOW();
 }
 
 void img_ccw(struct image *is,struct image *id)
@@ -382,6 +393,7 @@ void img_ccw(struct image *is,struct image *id)
    i=is->xsize;
    src=is->img+is->xsize-1;
    dest=id->img+is->xsize*is->ysize;
+   THREADS_ALLOW();
    while (i--)
    {
       j=is->ysize;
@@ -389,11 +401,12 @@ void img_ccw(struct image *is,struct image *id)
       src--;
       src-=is->xsize*is->ysize;
    }
+   THREADS_DISALLOW();
 }
 
 void image_cw(INT32 args)
 {
-   INT32 i,j;
+   INT32 i,j,xs,ys;
    rgb_group *src,*dest;
    struct object *o;
    struct image *img;
@@ -410,18 +423,20 @@ void image_cw(INT32 args)
       free_object(o);
       error("Out of memory\n");
    }
-   img->xsize=THIS->ysize;
-   img->ysize=THIS->xsize;
-   i=THIS->xsize;
+   ys=img->xsize=THIS->ysize;
+   i=xs=img->ysize=THIS->xsize;
+
    src=THIS->img+THIS->xsize-1;
    dest=img->img+THIS->xsize*THIS->ysize;
+   THREADS_ALLOW();
    while (i--)
    {
-      j=THIS->ysize;
-      while (j--) *(--dest)=*(src),src+=THIS->xsize;
+      j=ys;
+      while (j--) *(--dest)=*(src),src+=xs;
       src--;
-      src-=THIS->xsize*THIS->ysize;
+      src-=xs*ys;
    }
+   THREADS_DISALLOW();
 
    push_object(o);
 }
@@ -431,7 +446,7 @@ void image_mirrorx(INT32 args)
    rgb_group *src,*dest;
    struct object *o;
    struct image *img;
-   INT32 i,j;
+   INT32 i,j,xs;
 
    pop_n_elems(args);
 
@@ -449,12 +464,15 @@ void image_mirrorx(INT32 args)
    i=THIS->ysize;
    src=THIS->img+THIS->xsize-1;
    dest=img->img;
+   xs=THIS->xsize;
+   THREADS_ALLOW();
    while (i--)
    {
-      j=THIS->xsize;
+      j=xs;
       while (j--) *(dest++)=*(src--);
-      src+=THIS->xsize*2;
+      src+=xs*2;
    }
+   THREADS_DISALLOW();
 
    push_object(o);
 }
@@ -464,7 +482,7 @@ void image_mirrory(INT32 args)
    rgb_group *src,*dest;
    struct object *o;
    struct image *img;
-   INT32 i,j;
+   INT32 i,j,xs;
 
    pop_n_elems(args);
 
@@ -482,12 +500,15 @@ void image_mirrory(INT32 args)
    i=THIS->ysize;
    src=THIS->img+THIS->xsize*(THIS->ysize-1);
    dest=img->img;
+   xs=THIS->xsize;
+   THREADS_ALLOW();
    while (i--)
    {
-      j=THIS->xsize;
+      j=xs;
       while (j--) *(dest++)=*(src++);
-      src-=THIS->xsize*2;
+      src-=xs*2;
    }
+   THREADS_DISALLOW();
 
    push_object(o);
  
@@ -506,6 +527,7 @@ static void img_skewx(struct image *src,
    rgb_group *s,*d;
    rgb_group rgb;
 
+   THREADS_ALLOW();
    if (dest->img) free(dest->img);
    if (diff<0) 
       dest->xsize=ceil(-diff)+src->xsize,x0=-diff;
@@ -566,6 +588,7 @@ static void img_skewx(struct image *src,
       while (j--) *(d++)=rgb;
       x0+=xmod;
    }
+   THREADS_DISALLOW();
 
    CHRONO("skewx end\n");
 }
@@ -580,6 +603,7 @@ static void img_skewy(struct image *src,
    rgb_group *s,*d;
    rgb_group rgb;
 
+   THREADS_ALLOW();
    if (dest->img) free(dest->img);
    if (diff<0) 
       dest->ysize=ceil(-diff)+src->ysize,y0=-diff;
@@ -642,6 +666,7 @@ CHRONO("skewy begin\n");
       d-=dest->ysize*xsz-1;
       y0+=ymod;
    }
+   THREADS_DISALLOW();
 
 CHRONO("skewy end\n");
 
diff --git a/src/modules/image/operator.c b/src/modules/image/operator.c
index ae28b90237dd7fbaf89e76b84a47ead6ce0927e3..2ad048ce38fbf96a6b19b33503aed2514e8e50e5 100644
--- a/src/modules/image/operator.c
+++ b/src/modules/image/operator.c
@@ -1,4 +1,4 @@
-/* $Id: operator.c,v 1.3 1996/12/10 01:42:47 law Exp $ */
+/* $Id: operator.c,v 1.4 1997/01/07 00:41:44 law Exp $ */
 #include "global.h"
 
 #include <math.h>
@@ -14,6 +14,7 @@
 #include "svalue.h"
 #include "array.h"
 #include "error.h"
+#include "threads.h"
 
 #include "image.h"
 
@@ -72,6 +73,7 @@ struct program *image_program;
    d=img->img;		   		   			\
 		   		   		   		\
    i=img->xsize*img->ysize;			   		\
+   THREADS_ALLOW();                                             \
    if (oper)
 
 
@@ -93,6 +95,7 @@ STANDARD_OPERATOR_HEADER("'-")
       d->b=absdiff(s1->b,rgb.b);
       s1++; d++;
    }
+   THREADS_DISALLOW();
 }
 
 void image_operator_plus(INT32 args)
@@ -113,6 +116,7 @@ STANDARD_OPERATOR_HEADER("'+")
       d->b=max(s1->b+rgb.b,255);
       s1++; d++;
    }
+   THREADS_DISALLOW();
 }
 
 void image_operator_multiply(INT32 args)
@@ -134,6 +138,7 @@ STANDARD_OPERATOR_HEADER("'+")
       d->b=floor(s1->b*rgb.b*q+0.5);
       s1++; d++; 
    }
+   THREADS_DISALLOW();
 }
 
 void image_operator_maximum(INT32 args)
@@ -154,6 +159,7 @@ STANDARD_OPERATOR_HEADER("'| 'maximum'")
       d->b=max(s1->b,rgb.b);
       s1++; s2++; d++; 
    }
+   THREADS_DISALLOW();
 }
 
 void image_operator_minimum(INT32 args)
@@ -174,6 +180,7 @@ STANDARD_OPERATOR_HEADER("'& 'minimum'")
       d->b=min(s1->b,rgb.b);
       s1++; d++; 
    }
+   THREADS_DISALLOW();
 }
 
 
diff --git a/src/modules/image/quant.c b/src/modules/image/quant.c
index e1144387193ceb5a1b563ed1023ae210a8cb2bf4..3657c7034534f1e933c784090787053f98389793 100644
--- a/src/modules/image/quant.c
+++ b/src/modules/image/quant.c
@@ -1,4 +1,4 @@
-/* $Id: quant.c,v 1.20 1996/12/12 20:03:46 law Exp $ */
+/* $Id: quant.c,v 1.21 1997/01/07 00:41:45 law Exp $ */
 
 /*
 
@@ -14,6 +14,7 @@ David K
 
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
+#include "threads.h"
 #endif
 
 #include "types.h"
@@ -500,6 +501,7 @@ struct colortable *colortable_quant(struct image *img,int numcol)
    INT32 entries=0;
    unsigned long *next_free_rgb_node;
 
+   THREADS_ALLOW();
 #ifdef QUANT_DEBUG
    fprintf(stderr,"img_quant called\n");
 #endif
@@ -589,6 +591,7 @@ struct colortable *colortable_quant(struct image *img,int numcol)
 
    free(tbl);
    CHRONO("really done");
+   THREADS_DISALLOW();
    return ct;
 }
 
@@ -604,6 +607,7 @@ struct colortable *colortable_from_array(struct array *arr,char *from)
    struct svalue s,s2;
    unsigned long *next_free_rgb_node;
 
+   THREADS_ALLOW();
 #ifdef QUANT_DEBUG
    fprintf(stderr,"ctfa called\n");
 #endif
@@ -656,6 +660,7 @@ struct colortable *colortable_from_array(struct array *arr,char *from)
 	 ct->cache[i].value=j;
 
    CHRONO("really done");
+   THREADS_DISALLOW();
    return ct;
 }
 
diff --git a/src/modules/image/togif.c b/src/modules/image/togif.c
index 46894cd10ba5c70926da31b67f86ad3cfabb58e3..0b17c9e2b7050900ae5e96fcca4a9dab365f0efd 100644
--- a/src/modules/image/togif.c
+++ b/src/modules/image/togif.c
@@ -1,4 +1,4 @@
-/* $Id: togif.c,v 1.21 1996/12/10 00:40:11 law Exp $ */
+/* $Id: togif.c,v 1.22 1997/01/07 00:41:47 law Exp $ */
 /*
 
 togif 
@@ -14,6 +14,7 @@ Pontus Hagland, law@infovav.se
 
 #include "stralloc.h"
 #include "global.h"
+#include "threads.h"
 #include "types.h"
 #include "macros.h"
 #include "object.h"
@@ -253,6 +254,7 @@ CHRONO("image_encode_gif begin");
 
 CHRONO("image_encode_gif header done");
 
+THREADS_ALLOW();
    lzw_init(&lzw,bpp);
    if (!fs)
       while (i--) lzw_add(&lzw,colortable_rgb(ct,*(rgb++)));
@@ -303,6 +305,7 @@ CHRONO("image_encode_gif wrote ok");
    low_my_putchar( ';', &buf ); /* end gif file */
 
 CHRONO("image_encode_gif done");
+THREADS_DISALLOW();
 
    return low_free_buf(&buf);
 }
@@ -339,6 +342,7 @@ int image_decode_gif(struct image *dest,struct image *dest_alpha,
 
    bpp=(src[10]&7)+1;
 
+   THREADS_ALLOW();
    if (src[10]&128)
    {
       global_palette=(rgb_group*)(src+13);
@@ -433,6 +437,7 @@ int image_decode_gif(struct image *dest,struct image *dest_alpha,
       }
    }
    while (0);
+   THREADS_DISALLOW();
 
    if (arena) free(arena);
    return 1; /* ok */
@@ -699,6 +704,7 @@ CHRONO("gif add init");
 
 CHRONO("begin pack");
 
+   THREADS_ALLOW();
    lzw_init(&lzw,bpp);
    if (!fs)
       while (i--) lzw_add(&lzw,colortable_rgb(ct,*(rgb++)));
@@ -745,6 +751,7 @@ CHRONO("end pack");
    lzw_quit(&lzw);
 
    colortable_free(ct);
+   THREADS_DISALLOW();
 
 CHRONO("done");