diff --git a/src/modules/_Image_JPEG/image_jpeg.c b/src/modules/_Image_JPEG/image_jpeg.c
index 2dc08f112cfd2e6bc71c3eeee2bbe4d5b1af6426..39d9df569c0c97e349b949c196d22726f955019c 100644
--- a/src/modules/_Image_JPEG/image_jpeg.c
+++ b/src/modules/_Image_JPEG/image_jpeg.c
@@ -1,5 +1,5 @@
 /*
- * $Id: image_jpeg.c,v 1.17 1998/05/13 18:47:48 grubba Exp $
+ * $Id: image_jpeg.c,v 1.18 1998/06/19 12:55:24 mirar Exp $
  */
 
 #include "config.h"
@@ -22,7 +22,7 @@
 #undef HAVE_STDLIB_H
 #endif
 #include "global.h"
-RCSID("$Id: image_jpeg.c,v 1.17 1998/05/13 18:47:48 grubba Exp $");
+RCSID("$Id: image_jpeg.c,v 1.18 1998/06/19 12:55:24 mirar Exp $");
 
 #include "pike_macros.h"
 #include "object.h"
@@ -34,7 +34,6 @@ RCSID("$Id: image_jpeg.c,v 1.17 1998/05/13 18:47:48 grubba Exp $");
 #include "mapping.h"
 #include "error.h"
 #include "stralloc.h"
-#include "dynamic_buffer.h"
 
 #ifdef HAVE_JPEGLIB_H
 
@@ -239,6 +238,11 @@ static void my_term_source(struct jpeg_decompress_struct *cinfo)
 **!		DEFAULT and FASTEST is from the jpeg library,
 **!		probably ISLOW and IFAST respective.
 **!
+**!	    "density_unit":int
+**!	    "x_density":int
+**!	    "y_density":int
+**!		density of image; unit is 1:dpi 2:dpcm 0:no units
+**!
 **!	wizard options:
 **!	    "baseline":0|1
 **!		Force baseline output. Useful for quality<20.
@@ -474,9 +478,12 @@ static void image_jpeg_decode(INT32 args)
 
    jpeg_read_header(&cinfo,TRUE);
 
-   /* we can only handle RGB */
+   /* we can only handle RGB or GRAYSCALE */
 
-   cinfo.out_color_space=JCS_RGB;
+   if (cinfo.jpeg_color_space==JCS_GRAYSCALE)
+      cinfo.out_color_space=JCS_GRAYSCALE;
+   else
+      cinfo.out_color_space=JCS_RGB;
 
    /* check configuration */
 
@@ -553,11 +560,14 @@ static void image_jpeg_decode(INT32 args)
 
       s=tmp;
       m=img->xsize*n;
-      while (m--)
-	 d->r=*(s++),
-	 d->g=*(s++),
-	 d->b=*(s++),d++;
-
+      if (cinfo.out_color_space==JCS_RGB)
+	 while (m--)
+	    d->r=*(s++),
+	    d->g=*(s++),
+	    d->b=*(s++),d++;
+      else
+	 while (m--)
+	    d->r=d->g=d->b=*(s++),d++;
       y-=n;
    }
 
@@ -571,6 +581,145 @@ static void image_jpeg_decode(INT32 args)
    jpeg_destroy_decompress(&cinfo);
 }
 
+/*
+**! method object decode_header(string data)
+**! method object decode_header(string data, mapping options)
+**! 	Decodes a JPEG image header. 
+**!
+**!	<pre>
+**!	    "xsize":int
+**!	    "ysize":int
+**!		size of image
+**!	    "xdpi":float
+**!	    "ydpi":float
+**!		image dpi, if known
+**!	    "type":"image/jpeg"
+**!		file type information as MIME type
+**!
+**!	JPEG specific:
+**!	    "num_compontents":int
+**!		number of channels in JPEG image
+**!	    "color_space":"GRAYSCALE"|"RGB"|"YUV"|"CMYK"|"YCCK"|"UNKNOWN"
+**!		color space of JPEG image
+**!	    "density_unit":int
+**!	    "x_density":int
+**!	    "y_density":int
+**!		density of image; unit is 1:dpi 2:dpcm 0:no units
+**!	    "adobe_marker":0|1
+**!		if the file has an adobe marker
+**!	</pre>
+**!
+**! note
+**!	Please read some about JPEG files. 
+*/
+
+static void image_jpeg_decode_header(INT32 args)
+{
+   struct jpeg_error_mgr errmgr;
+   struct my_source_mgr srcmgr;
+   struct jpeg_decompress_struct cinfo;
+
+   struct image *img;
+
+   int n=0;
+
+   if (args<1 
+       || sp[-args].type!=T_STRING
+       || (args>1 && sp[1-args].type!=T_MAPPING))
+      error("Image.JPEG.decode_header: Illegal arguments\n");
+
+   pop_n_elems(args-1);
+
+   /* init jpeg library objects */
+
+   jpeg_std_error(&errmgr);
+
+   errmgr.error_exit=my_error_exit;
+   errmgr.emit_message=my_emit_message;
+   errmgr.output_message=my_output_message;
+
+   srcmgr.pub.init_source=my_init_source;
+   srcmgr.pub.fill_input_buffer=my_fill_input_buffer;
+   srcmgr.pub.skip_input_data=my_skip_input_data;
+   srcmgr.pub.resync_to_restart=jpeg_resync_to_restart;
+   srcmgr.pub.term_source=my_term_source;
+   srcmgr.str=sp[-args].u.string;
+
+   cinfo.err=&errmgr;
+
+   jpeg_create_decompress(&cinfo);
+
+   cinfo.src=(struct jpeg_source_mgr*)&srcmgr;
+
+   jpeg_read_header(&cinfo,TRUE);
+
+   /* standard header info */
+
+   push_text("type"); n++;
+   push_text("image/jpeg");
+
+   push_text("xsize"); n++;
+   push_int(cinfo.image_width);
+
+   push_text("ysize"); n++;
+   push_int(cinfo.image_height);
+
+   push_text("xdpi"); n++;
+   push_text("ydpi"); n++;
+   switch (cinfo.density_unit)
+   {
+      default:
+	 pop_n_elems(2); n-=2;
+	 break;
+      case 1:
+	 push_float( cinfo.X_density );
+	 stack_swap();
+	 push_float( cinfo.Y_density );
+	 break;
+      case 2:
+	 push_float( cinfo.X_density/2.54 );
+	 stack_swap();
+	 push_float( cinfo.Y_density/2.54 );
+	 break;
+   }
+
+   /* JPEG special header */
+
+   push_text("num_components"); n++;
+   push_int(cinfo.num_components);
+
+   push_text("color_space"); n++;
+   switch (cinfo.jpeg_color_space)
+   {
+      case JCS_UNKNOWN:	  push_text("UNKNOWN"); break;
+      case JCS_GRAYSCALE: push_text("GRAYSCALE"); break;
+      case JCS_RGB:	  push_text("RGB"); break;
+      case JCS_YCbCr:	  push_text("YUV"); break;
+      case JCS_CMYK:	  push_text("CMYK"); break;
+      case JCS_YCCK:	  push_text("YCCK"); break;
+      default:		  push_text("?"); break;
+   }
+
+   push_text("density_unit"); n++;
+   push_int(cinfo.density_unit);
+
+   push_text("x_density"); n++;
+   push_int(cinfo.X_density);
+
+   push_text("y_density"); n++;
+   push_int(cinfo.Y_density);
+
+   push_text("adobe_marker"); n++;
+   push_int(cinfo.saw_Adobe_marker);
+
+   f_aggregate_mapping(n*2);
+
+   stack_swap();
+   pop_stack();
+
+   jpeg_destroy_decompress(&cinfo);
+}
+
 #endif /* HAVE_JPEGLIB_H */
 
 /*** module init & exit & stuff *****************************************/
@@ -616,6 +765,8 @@ void pike_module_init(void)
    {
       add_function("decode",image_jpeg_decode,
 		   "function(string,void|mapping(string:int):object)",0);
+      add_function("decode_header",image_jpeg_decode_header,
+		   "function(string,void|mapping(string:int):object)",0);
       add_function("encode",image_jpeg_encode,
 		   "function(object,void|mapping(string:int):string)",0);