diff --git a/src/modules/Image/encodings/pnm.c b/src/modules/Image/encodings/pnm.c
index 0cafbf160853ff4131d37deac372b7efae83d142..4203531cdadd506e4b0af01a0206346f3a0e32f1 100644
--- a/src/modules/Image/encodings/pnm.c
+++ b/src/modules/Image/encodings/pnm.c
@@ -1,9 +1,9 @@
-/* $Id: pnm.c,v 1.7 1998/01/08 20:51:39 mirar Exp $ */
+/* $Id: pnm.c,v 1.8 1998/01/13 01:32:20 mirar Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: pnm.c,v 1.7 1998/01/08 20:51:39 mirar Exp $
+**!	$Id: pnm.c,v 1.8 1998/01/13 01:32:20 mirar Exp $
 **! submodule PNM
 **!
 **!	This submodule keeps the PNM encode/decode capabilities
@@ -49,7 +49,7 @@
 
 #include "stralloc.h"
 #include "global.h"
-RCSID("$Id: pnm.c,v 1.7 1998/01/08 20:51:39 mirar Exp $");
+RCSID("$Id: pnm.c,v 1.8 1998/01/13 01:32:20 mirar Exp $");
 #include "pike_macros.h"
 #include "object.h"
 #include "constants.h"
@@ -230,12 +230,12 @@ void img_pnm_decode(INT32 args)
 /*
 **! method string encode(object image)
 **! method string encode_binary(object image)
-**  method string encode_ascii(object image)
-**  method string encode_P1(object image)
-**  method string encode_P2(object image)
-**  method string encode_P3(object image)
-**  method string encode_P4(object image)
-**  method string encode_P5(object image)
+**! method string encode_ascii(object image)
+**! method string encode_P1(object image)
+**! method string encode_P2(object image)
+**! method string encode_P3(object image)
+**! method string encode_P4(object image)
+**! method string encode_P5(object image)
 **! method string encode_P6(object image)
 **  method string encode_P7(object image)
 **!	Make a complete PNM file from an image.
@@ -244,17 +244,222 @@ void img_pnm_decode(INT32 args)
 **!	uses the most optimized encoding for this image (bitmap, grey
 **!	or truecolor) - P4, P5 or P6 respective P1, P2 or P3.
 **!
-**!	<ref>encode</ref>() maps to <ref>encode_binary</ref>().
-**! 	
 **! see also: decode
 **!
 **! returns the encoded image as a string
 **!
-**! bugs
-**!	Currently only supports type P5 (binary grey) and
-**!	P6 (binary truecolor). 
+**! note
+**!	<ref>encode</ref>() is equal to <ref>encode_binary</ref>(),
+**!	but may change in a future release.
 */
 
+void img_pnm_encode_P1(INT32 args) /* ascii PBM */
+{
+   char buf[80];
+   struct pike_string *a,*b;
+   struct image *img;
+   unsigned char *c;
+   int x,y;
+   rgb_group *s;
+
+   if (args<1 ||
+       sp[-args].type!=T_OBJECT ||
+       !(img=(struct image*)get_storage(sp[-args].u.object,image_program)))
+      error("Image.PNM.encode_P1(): Illegal arguments\n");
+   if (!img->img)
+      error("Image.PNM.encode_P1(): Given image is empty\n");
+
+   sprintf(buf,"P1\n%d %d\n",img->xsize,img->ysize);
+   a=make_shared_string(buf);
+
+   y=img->ysize;
+   s=img->img;
+   c=(unsigned char*)((b=begin_shared_string((img->xsize*2)*
+					     img->ysize))->str);
+   if (img->xsize)
+   while (y--)
+   {
+      x=img->xsize;
+      while (x--)
+      {
+	 *(c++)=48+!(s->r|s->g|s->b);
+	 *(c++)=' ';
+	 s++;
+      }
+      *(c-1)='\n';
+   }
+   b=end_shared_string(b);
+
+   pop_n_elems(args);
+   push_string(add_shared_strings(a,b));
+   free_string(a);
+   free_string(b);
+}
+
+extern void f_add(INT32 args);
+
+void img_pnm_encode_P2(INT32 args) /* ascii PGM */
+{
+   char buf[80];
+   struct image *img;
+   int y,x;
+   rgb_group *s;
+   int n;
+   struct object *o;
+
+   if (args<1 ||
+       sp[-args].type!=T_OBJECT ||
+       !(img=(struct image*)get_storage((o=sp[-args].u.object),image_program)))
+      error("Image.PNM.encode_P2(): Illegal arguments\n");
+   if (!img->img)
+      error("Image.PNM.encode_P2(): Given image is empty\n");
+
+   o->refs++;
+   pop_n_elems(args);
+
+   sprintf(buf,"P2\n%d %d\n255\n",img->xsize,img->ysize);
+   push_string(make_shared_string(buf));
+   n=1;
+
+   y=img->ysize;
+   s=img->img;
+   while (y--)
+   {
+      x=img->xsize;
+      while (x--)
+      {
+	 sprintf(buf,"%d%c",(s->r+s->g*2+s->b)/4,x?' ':'\n');
+	 push_string(make_shared_string(buf));
+	 n++;
+	 if (n>32) { f_add(n); n=1; }
+	 s++;
+      }
+   }
+   f_add(n);
+   free_object(o);
+}
+
+void img_pnm_encode_P3(INT32 args) /* ascii PPM */
+{
+   char buf[80];
+   struct image *img;
+   int y,x;
+   rgb_group *s;
+   int n;
+   struct object *o;
+
+   if (args<1 ||
+       sp[-args].type!=T_OBJECT ||
+       !(img=(struct image*)get_storage((o=sp[-args].u.object),image_program)))
+      error("Image.PNM.encode_P3(): Illegal arguments\n");
+   if (!img->img)
+      error("Image.PNM.encode_P3(): Given image is empty\n");
+
+   o->refs++;
+   pop_n_elems(args);
+
+   sprintf(buf,"P3\n%d %d\n255\n",img->xsize,img->ysize);
+   push_string(make_shared_string(buf));
+   n=1;
+
+   y=img->ysize;
+   s=img->img;
+   while (y--)
+   {
+      x=img->xsize;
+      while (x--)
+      {
+	 sprintf(buf,"%d %d %d%c",s->r,s->g,s->b,x?' ':'\n');
+	 push_string(make_shared_string(buf));
+	 n++;
+	 if (n>32) { f_add(n); n=1; }
+	 s++;
+      }
+   }
+   f_add(n);
+   free_object(o);
+}
+
+void img_pnm_encode_P4(INT32 args) /* binary PBM */
+{
+   char buf[80];
+   struct pike_string *a,*b;
+   struct image *img;
+   unsigned char *c;
+   int y,x,bit;
+   rgb_group *s;
+
+   if (args<1 ||
+       sp[-args].type!=T_OBJECT ||
+       !(img=(struct image*)get_storage(sp[-args].u.object,image_program)))
+      error("Image.PNM.encode_P4(): Illegal arguments\n");
+   if (!img->img)
+      error("Image.PNM.encode_P4(): Given image is empty\n");
+
+   sprintf(buf,"P4\n%d %d\n",img->xsize,img->ysize);
+   a=make_shared_string(buf);
+
+   y=img->ysize;
+   s=img->img;
+   c=(unsigned char*)((b=begin_shared_string(((img->xsize+7)>>3)*
+					     img->ysize))->str);
+   if (img->xsize)
+   while (y--)
+   {
+      x=img->xsize;
+      bit=128;
+      *c=0;
+      while (x--)
+      {
+	 *c|=bit*!(s->r|s->g|s->b);
+	 if (!(bit>>=1)) { *(++c)=0; bit=128; }
+	 s++;
+      }
+      if (y && bit>1) *(++c)=0; 
+   }
+   b=end_shared_string(b);
+
+   pop_n_elems(args);
+   push_string(add_shared_strings(a,b));
+   free_string(a);
+   free_string(b);
+}
+
+void img_pnm_encode_P5(INT32 args) /* binary PGM */
+{
+   char buf[80];
+   struct pike_string *a,*b;
+   struct image *img;
+   unsigned char *c;
+   int n;
+   rgb_group *s;
+
+   if (args<1 ||
+       sp[-args].type!=T_OBJECT ||
+       !(img=(struct image*)get_storage(sp[-args].u.object,image_program)))
+      error("Image.PNM.encode_P5(): Illegal arguments\n");
+   if (!img->img)
+      error("Image.PNM.encode_P5(): Given image is empty\n");
+
+   sprintf(buf,"P5\n%d %d\n255\n",img->xsize,img->ysize);
+   a=make_shared_string(buf);
+
+   n=img->xsize*img->ysize;
+   s=img->img;
+   c=(unsigned char*)((b=begin_shared_string(n))->str);
+   while (n--)
+   {
+      *(c++)=(s->r+s->g*2+s->b)/4;
+      s++;
+   }
+   b=end_shared_string(b);
+
+   pop_n_elems(args);
+   push_string(add_shared_strings(a,b));
+   free_string(a);
+   free_string(b);
+}
+
 void img_pnm_encode_P6(INT32 args)
 {
    char buf[80];
@@ -295,9 +500,72 @@ void img_pnm_encode_P6(INT32 args)
 }
 
 
+void img_pnm_encode_ascii(INT32 args)
+{
+   struct image *img;
+   rgb_group *s;
+   int n;
+   void (*func)(INT32);
+
+   if (args<1 ||
+       sp[-args].type!=T_OBJECT ||
+       !(img=(struct image*)get_storage(sp[-args].u.object,image_program)))
+      error("Image.PNM.encode_binary(): Illegal arguments\n");
+   if (!img->img)
+      error("Image.PNM.encode_binary(): Given image is empty\n");
+
+   func=img_pnm_encode_P1; /* PBM */
+   n=img->xsize*img->ysize;
+   s=img->img;
+   while (n--)
+   {
+      if (s->r!=s->g || s->g!=s->b)
+      {
+	 func=img_pnm_encode_P3; 
+	 break;
+      }
+      else if ((s->r!=0 && s->r!=255) ||
+	       (s->g!=0 && s->g!=255) ||
+	       (s->b!=0 && s->b!=255))
+	 func=img_pnm_encode_P2; 
+      s++;
+   }
+
+   (*func)(args);
+}
+
 void img_pnm_encode_binary(INT32 args)
 {
-   img_pnm_encode_P6(args);
+   struct image *img;
+   rgb_group *s;
+   int n;
+   void (*func)(INT32);
+
+   if (args<1 ||
+       sp[-args].type!=T_OBJECT ||
+       !(img=(struct image*)get_storage(sp[-args].u.object,image_program)))
+      error("Image.PNM.encode_binary(): Illegal arguments\n");
+   if (!img->img)
+      error("Image.PNM.encode_binary(): Given image is empty\n");
+
+   func=img_pnm_encode_P4; /* PBM */
+   n=img->xsize*img->ysize;
+   s=img->img;
+   while (n--)
+   {
+      if (s->r!=s->g || s->g!=s->b)
+      {
+	 func=img_pnm_encode_P6; 
+	 break;
+      }
+      else if ((s->r!=0 && s->r!=255) ||
+	       (s->g!=0 && s->g!=255) ||
+	       (s->b!=0 && s->b!=255))
+	 func=img_pnm_encode_P5; 
+      s++;
+   }
+
+   (*func)(args);
 }
 
 
@@ -311,6 +579,20 @@ void init_image_pnm(void)
 		"function(object:string)",0);
    add_function("encode_binary",img_pnm_encode_binary,
 		"function(object:string)",0);
+   add_function("encode_ascii",img_pnm_encode_ascii,
+		"function(object:string)",0);
+
+   add_function("encode_P1",img_pnm_encode_P1,
+		"function(object:string)",0);
+   add_function("encode_P2",img_pnm_encode_P2,
+		"function(object:string)",0);
+   add_function("encode_P3",img_pnm_encode_P3,
+		"function(object:string)",0);
+
+   add_function("encode_P4",img_pnm_encode_P4,
+		"function(object:string)",0);
+   add_function("encode_P5",img_pnm_encode_P5,
+		"function(object:string)",0);
    add_function("encode_P6",img_pnm_encode_P6,
 		"function(object:string)",0);