From 451f5d338ecfa8ecdbdacdc613a943e38de5744a Mon Sep 17 00:00:00 2001
From: "Mirar (Pontus Hagland)" <pike@sort.mirar.org>
Date: Sun, 25 Jan 1998 12:32:26 +0100
Subject: [PATCH] hackade in JPEG.decode...

Rev: src/modules/_Image_JPEG/image_jpeg.c:1.7
---
 src/modules/_Image_JPEG/image_jpeg.c | 238 ++++++++++++++++++++++++++-
 1 file changed, 232 insertions(+), 6 deletions(-)

diff --git a/src/modules/_Image_JPEG/image_jpeg.c b/src/modules/_Image_JPEG/image_jpeg.c
index 7ddfc6007f..a79c4c8ab0 100644
--- a/src/modules/_Image_JPEG/image_jpeg.c
+++ b/src/modules/_Image_JPEG/image_jpeg.c
@@ -43,6 +43,10 @@ static struct pike_string *param_density;
 static struct pike_string *param_density_unit;
 static struct pike_string *param_method;
 static struct pike_string *param_progressive;
+static struct pike_string *param_block_smoothing;
+static struct pike_string *param_scale_denom;
+static struct pike_string *param_scale_num;
+static struct pike_string *param_fancy_upsampling;
 
 #ifdef HAVE_JPEGLIB_H
 
@@ -66,7 +70,7 @@ static void my_error_exit(struct jpeg_common_struct *cinfo)
    char buffer[JMSG_LENGTH_MAX];
    (*cinfo->err->format_message) (cinfo, buffer);
 
-   jpeg_abort(cinfo);
+   jpeg_destroy(cinfo);
    error("Image.JPEG: fatal error in libjpeg; %s\n",buffer);
 }
 
@@ -97,7 +101,7 @@ static void my_init_destination(struct jpeg_compress_struct *cinfo)
    dm->pub.next_output_byte=(JOCTET*)dm->buf;
 }
 
-boolean my_empty_output_buffer(struct jpeg_compress_struct *cinfo)
+static boolean my_empty_output_buffer(struct jpeg_compress_struct *cinfo)
 {
    struct my_destination_mgr *dm=(struct my_destination_mgr *)cinfo->dest;
    int pos;
@@ -148,12 +152,49 @@ int parameter_int(struct svalue *map,struct pike_string *what,INT32 *p)
    return 1;
 }
 
-/*
-**! method object decode(string data)
-*/
 
-static void image_jpeg_decode(INT32 args)
+
+struct my_source_mgr
+{
+   struct jpeg_source_mgr pub;
+   struct pike_string *str;
+};
+
+static void my_init_source(struct jpeg_decompress_struct *cinfo)
+{
+  struct my_source_mgr *sm=(struct my_source_mgr *)cinfo->src;
+  
+  sm->pub.next_input_byte=(JOCTET*)sm->str->str;
+  sm->pub.bytes_in_buffer=sm->str->len;
+}
+
+static boolean my_fill_input_buffer(struct jpeg_decompress_struct *cinfo)
+{
+   static unsigned char my_eoi[2]={0xff,JPEG_EOI};
+
+   struct my_source_mgr *sm=(struct my_source_mgr *)cinfo->src;
+
+   sm->pub.next_input_byte=my_eoi;
+   sm->pub.bytes_in_buffer=2;
+
+   return TRUE; /* hope this works */
+}
+
+static void my_skip_input_data(struct jpeg_decompress_struct *cinfo,
+			       long num_bytes)
+{
+   struct my_source_mgr *sm=(struct my_source_mgr *)cinfo->src;
+ 
+   if (num_bytes>sm->pub.bytes_in_buffer)
+      num_bytes=sm->pub.bytes_in_buffer;
+
+   sm->pub.next_input_byte += (size_t) num_bytes;
+   sm->pub.bytes_in_buffer -= (size_t) num_bytes;
+}
+
+static void my_term_source(struct jpeg_decompress_struct *cinfo)
 {
+   /* nop */
 }
 
 /*
@@ -332,6 +373,8 @@ static void image_jpeg_encode(INT32 args)
       y-=y2;
    }
 
+   free(tmp);
+
    jpeg_finish_compress(&cinfo);
 
    pop_n_elems(args);
@@ -340,6 +383,181 @@ static void image_jpeg_encode(INT32 args)
    jpeg_destroy_compress(&cinfo);
 }
 
+/*
+**! method object decode(string data)
+**! method object decode(string data, mapping options)
+**! 	Decodes a JPEG image. 
+**!
+**!     The <tt>options<tt> argument may be a mapping
+**!	containing zero or more encoding options:
+**!
+**!	<pre>
+**!	advanced options:
+**!	    "block_smoothing":0|1
+**!		Do interblock smoothing. Default is on (1).
+**!	    "fancy_upsampling":0|1
+**!		Do fancy upsampling of chroma components. 
+**!		Default is on (1).
+**!	    "method":JPEG.IFAST|JPEG.ISLOW|JPEG.FLOAT|JPEG.DEFAULT|JPEG.FASTEST
+**!		DCT method to use.
+**!		DEFAULT and FASTEST is from the jpeg library,
+**!		probably ISLOW and IFAST respective.
+**!
+**!	wizard options:
+**!	    "scale_num":1..
+**!	    "scale_denom":1..
+**!	        Rescale the image when read from JPEG data.
+**!		My (Mirar) version (6a) of jpeglib can only handle
+**!		1/1, 1/2, 1/4 and 1/8. 
+**!
+**!	wizard options:
+**!	    "baseline":0|1
+**!		Force baseline output. Useful for quality<20.
+**!	</pre>
+**!
+**! note
+**!	Please read some about JPEG files. 
+*/
+
+static void image_jpeg_decode(INT32 args)
+{
+   struct jpeg_error_mgr errmgr;
+   struct my_source_mgr srcmgr;
+   struct jpeg_decompress_struct cinfo;
+
+   struct object *o;
+   struct image *img;
+
+   unsigned char *tmp,*s;
+   INT32 y;
+   rgb_group *d;
+   JSAMPROW row_pointer[8];
+
+   if (args<1 
+       || sp[-args].type!=T_STRING
+       || (args>1 && sp[1-args].type!=T_MAPPING))
+      error("Image.JPEG.decode: Illegal arguments\n");
+
+   /* 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);
+
+   /* we can only handle RGB */
+
+   cinfo.out_color_space=JCS_RGB;
+
+   /* check configuration */
+
+   if (args>1)
+   {
+      INT32 p,q;
+
+      p=0;
+      q=75;
+      if (parameter_int(sp+1-args,param_method,&p)
+	  && (p==JDCT_IFAST ||
+	      p==JDCT_FLOAT ||
+	      p==JDCT_DEFAULT ||
+	      p==JDCT_ISLOW ||
+	      p==JDCT_FASTEST))
+	 cinfo.dct_method=p;
+
+      if (parameter_int(sp+1-args,param_fancy_upsampling,&p))
+	 cinfo.do_fancy_upsampling=!!p;
+      
+      if (parameter_int(sp+1-args,param_block_smoothing,&p))
+	 cinfo.do_block_smoothing=!!p;
+      
+      if (parameter_int(sp+1-args,param_scale_denom,&p)
+	 &&parameter_int(sp+1-args,param_scale_num,&q))
+	 cinfo.scale_num=q,
+	 cinfo.scale_denom=p;
+   }
+
+   jpeg_start_decompress(&cinfo);
+
+   o=clone_object(image_program,0);
+   img=(struct image*)get_storage(o,image_program);
+   if (!img) error("image no image? foo?\n"); /* should never happen */
+   img->img=malloc(sizeof(rgb_group)*
+		   cinfo.output_width*cinfo.output_height);
+   if (!img->img)
+   {
+      jpeg_destroy((struct jpeg_common_struct*)&cinfo);
+      free_object(o);
+      error("Image.JPEG.decode: out of memory\n");
+   }
+   img->xsize=cinfo.output_width;
+   img->ysize=cinfo.output_height;
+
+   tmp=malloc(8*cinfo.output_width*cinfo.output_components);
+   if (!tmp)
+   {
+      jpeg_destroy((struct jpeg_common_struct*)&cinfo);
+      free_object(o);
+      error("Image.JPEG.decode: out of memory\n");
+   }
+   
+   y=img->ysize;
+   d=img->img;
+
+   while (y)
+   {
+      int n,m;
+
+      if (y<8) n=y; else n=8;
+
+      row_pointer[0]=tmp;
+      row_pointer[1]=tmp+img->xsize*3;
+      row_pointer[2]=tmp+img->xsize*3*2;
+      row_pointer[3]=tmp+img->xsize*3*3;
+      row_pointer[4]=tmp+img->xsize*3*4;
+      row_pointer[5]=tmp+img->xsize*3*5;
+      row_pointer[6]=tmp+img->xsize*3*6;
+      row_pointer[7]=tmp+img->xsize*3*7;
+
+      n=jpeg_read_scanlines(&cinfo, row_pointer, n);
+      /* read 8 rows */
+
+      s=tmp;
+      m=img->xsize*n;
+      while (m--)
+	 d->r=*(s++),
+	 d->g=*(s++),
+	 d->b=*(s++),d++;
+
+      y-=n;
+   }
+
+   free(tmp);
+
+   jpeg_finish_decompress(&cinfo);
+
+   pop_n_elems(args);
+   push_object(o);
+
+   jpeg_destroy_decompress(&cinfo);
+}
+
 #endif /* HAVE_JPEGLIB_H */
 
 /*** module init & exit & stuff *****************************************/
@@ -359,6 +577,10 @@ void pike_module_exit(void)
    free_string(param_density_unit);
    free_string(param_method);
    free_string(param_progressive);
+   free_string(param_fancy_upsampling);
+   free_string(param_block_smoothing);
+   free_string(param_scale_denom);
+   free_string(param_scale_num);
 }
 
 void pike_module_init(void)
@@ -411,4 +633,8 @@ void pike_module_init(void)
    param_density_unit=make_shared_string("density_unit");
    param_method=make_shared_string("method");
    param_progressive=make_shared_string("progressive");
+   param_scale_denom=make_shared_string("scale_denom");
+   param_scale_num=make_shared_string("scale_num");
+   param_fancy_upsampling=make_shared_string("fancy_upsampling");
+   param_block_smoothing=make_shared_string("block_smoothing");
 }
-- 
GitLab