From eb81e37e057f0a9fbfbe29522c89bfbc01637a08 Mon Sep 17 00:00:00 2001
From: "Mirar (Pontus Hagland)" <pike@sort.mirar.org>
Date: Sun, 2 May 1999 17:29:16 +0200
Subject: [PATCH] decoder works for 1,4,8 bits w/ alignment

Rev: src/modules/Image/encodings/bmp.c:1.7
---
 src/modules/Image/encodings/bmp.c | 87 +++++++++++++++++++++++--------
 1 file changed, 66 insertions(+), 21 deletions(-)

diff --git a/src/modules/Image/encodings/bmp.c b/src/modules/Image/encodings/bmp.c
index b031c922db..d4c759fa0f 100644
--- a/src/modules/Image/encodings/bmp.c
+++ b/src/modules/Image/encodings/bmp.c
@@ -1,9 +1,9 @@
-/* $Id: bmp.c,v 1.6 1999/05/01 20:17:28 mirar Exp $ */
+/* $Id: bmp.c,v 1.7 1999/05/02 15:29:16 mirar Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: bmp.c,v 1.6 1999/05/01 20:17:28 mirar Exp $
+**!	$Id: bmp.c,v 1.7 1999/05/02 15:29:16 mirar Exp $
 **! submodule BMP
 **!
 **!	This submodule keeps the BMP (Windows Bitmap)
@@ -22,7 +22,7 @@
 #include <ctype.h>
 
 #include "stralloc.h"
-RCSID("$Id: bmp.c,v 1.6 1999/05/01 20:17:28 mirar Exp $");
+RCSID("$Id: bmp.c,v 1.7 1999/05/02 15:29:16 mirar Exp $");
 #include "pike_macros.h"
 #include "object.h"
 #include "constants.h"
@@ -79,14 +79,23 @@ static INLINE unsigned long _int_from_16bit(unsigned char *data)
 /*
 **! method string encode(object image)
 **! method string encode(object image,object colortable)
+**  method string encode(object image,mapping options)
 **!	Make a BMP. It default to a 24 bpp BMP file,
 **!	but if a colortable is given, it will be 8bpp 
 **!	with a palette entry.
 **!
+** 	<tt>option</tt> is a mapping that may contain:
+** 	<pre>
+** 	"colortable": Image.Colortable   - palette
+** 	"bpp":        1|4|8|24           - force this many bits per pixel
+** 	"windows":    0|1                - windows mode (default is 1)
+** 	"rle":        0|1                - run-length encode (default is 0)
+** 	</pre>
+**!
 **! arg object image
 **!	Source image.
 **! arg object colortable
-**!	Colortable object. 
+**!	Colortable object, shortcut for "colortable" in options.
 **!
 **! see also: decode
 **!
@@ -125,7 +134,8 @@ void img_bmp_encode(INT32 args)
    else if (image_colortable_size(nct)<=256)
       bpp=8; /* only supports this for now */
    else
-      SIMPLE_BAD_ARG_ERROR("Image.BMP.encode",2,"colortable object with max 256 colors");
+      SIMPLE_BAD_ARG_ERROR("Image.BMP.encode",2,
+			   "colortable object with max 256 colors");
 
    if (oc) oc->refs++;
    o->refs++;
@@ -185,10 +195,10 @@ void img_bmp_encode(INT32 args)
    else
    {
       unsigned char *c;
-      int n=img->xsize*img->ysize;
+      int m=img->xsize*img->ysize;
       rgb_group *s=img->img;
-      c=(unsigned char*)((ps=begin_shared_string(n*3))->str);
-      while (n--)
+      c=(unsigned char*)((ps=begin_shared_string(m*3))->str);
+      while (m--)
       {
 	 *(c++)=s->b;
 	 *(c++)=s->g;
@@ -198,10 +208,14 @@ void img_bmp_encode(INT32 args)
       push_string(end_shared_string(ps));
       n++;
    }
+
+   /* on stack:      source (nct) info*n image */
    
    /* done */
    f_add(n);
 
+   /* on stack:      source (nct) info+image */
+
    /* "bitmapfileheader" */
    /* this is last, since we need to know the size of the file here */
    
@@ -214,8 +228,11 @@ void img_bmp_encode(INT32 args)
    push_ubo_32bit(offs+14);    /* offset to bitmap data */
 
    f_add(5);
-   stack_swap();
-   f_add(2);
+   
+   /* on stack:      source (nct) info+image header */
+
+   stack_swap();  /* source (nct) header info+image */
+   f_add(2);      /* source (nct) header+info+image */
 
    if (nct)
    {
@@ -230,6 +247,9 @@ void img_bmp_encode(INT32 args)
 **! method mapping _decode(string data)
 **! method mapping decode_header(string data)
 **! method object decode(string data)
+**! method mapping _decode(string data,mapping options)
+**! method mapping decode_header(string data,mapping options)
+**! method object decode(string data,mapping options)
 **!	Decode a BMP. Not all modes are supported.
 **!
 **!	<ref>decode</ref> gives an image object,
@@ -254,6 +274,17 @@ void img_bmp_encode(INT32 args)
 **!	Doesn't support all BMP modes. At all.
 */
 
+static int parameter_int(struct svalue *map,struct pike_string *what,INT32 *p)
+{
+   struct svalue *v;
+   v=low_mapping_string_lookup(map->u.mapping,what);
+
+   if (!v || v->type!=T_INT) return 0;
+
+   *p=v->u.integer;
+   return 1;
+}
+
 void i_img_bmp__decode(INT32 args,int header_only)
 {
    p_wchar0 *s,*os;
@@ -265,6 +296,7 @@ void i_img_bmp__decode(INT32 args,int header_only)
    rgb_group *d;
    int n=0,j,i,y,skip;
    int windows=0;
+   int quality=50; /* for JPEG decoding */
 
    if (args<1)
       SIMPLE_TOO_FEW_ARGS_ERROR("Image.BMP.decode",1);
@@ -274,6 +306,16 @@ void i_img_bmp__decode(INT32 args,int header_only)
    if (sp[-args].u.string->size_shift)
       SIMPLE_BAD_ARG_ERROR("Image.BMP.decode",1,"8 bit string");
 
+   if (args>1)
+      if (sp[1-args].type!=T_MAPPING)
+	 SIMPLE_BAD_ARG_ERROR("Image.BMP.decode",2,"mapping");
+      else
+      {
+	 struct pike_string *qs;
+	 MAKE_CONSTANT_SHARED_STRING(qs,"quality");
+	 parameter_int(sp+1-args,qs,&quality);
+      }
+
    os=s=(p_wchar0*)sp[-args].u.string->str;
    len=sp[-args].u.string->len;
    olen=len;
@@ -294,7 +336,8 @@ void i_img_bmp__decode(INT32 args,int header_only)
       case 68: /* fuji jpeg mode */
 
 	 if (len<54)
-	    error("Image.BMP.decode: unexpected EOF in header\n");
+	    error("Image.BMP.decode: unexpected EOF in header (at byte %d)\n",
+		  len);
 
 	 push_text("xsize");
 	 push_int(xsize=int_from_32bit(s+14+4*1));
@@ -347,8 +390,9 @@ void i_img_bmp__decode(INT32 args,int header_only)
 
       case 12: /* dos (?) mode */
 
-	 if (len<26)
-	    error("Image.BMP.decode: unexpected EOF in header\n");
+	 if (len<54)
+	    error("Image.BMP.decode: unexpected EOF in header (at byte %d)\n",
+		  len);
 
 	 push_text("xsize");
 	 push_int(xsize=int_from_16bit(s+14+4));
@@ -376,7 +420,8 @@ void i_img_bmp__decode(INT32 args,int header_only)
 	 break;
 
       default:
-	 error("Image.BMP.decode: not a BMP (illegal info size %ld, expected 40 or 12)\n",
+	 error("Image.BMP.decode: not a BMP "
+	       "(illegal info size %ld, expected 40 or 12)\n",
 	       int_from_32bit(s+14));
    }
 
@@ -416,7 +461,7 @@ void i_img_bmp__decode(INT32 args,int header_only)
       f_index(2);
       push_text("quant_tables");
       f_index(2);
-      push_int(55);
+      push_int(quality);
       f_call_function(2);
 
       f_aggregate_mapping(2);
@@ -497,7 +542,7 @@ void i_img_bmp__decode(INT32 args,int header_only)
 	 if (comp)
 	    error("Image.BMP.decode: can't handle compressed 8bpp BMP\n");
 
-	 skip=4-(img->xsize&3);
+	 skip=(4-img->xsize&3)&3;
 	 j=len;
 	 y=img->ysize;
 	 while (j && y--)
@@ -520,7 +565,7 @@ void i_img_bmp__decode(INT32 args,int header_only)
 	 }
 	 else
 	 {
-	    skip=3-((img->xsize/2)&3);
+	    skip=(4-((img->xsize+1)/2)&3)&3;
 	    j=len;
 	    y=img->ysize;
 	    while (j && y--)
@@ -541,7 +586,7 @@ void i_img_bmp__decode(INT32 args,int header_only)
 	 if (comp)
 	    error("Image.BMP.decode: can't handle compressed 1bpp BMP\n");
 
-	 skip=3-((img->xsize/8)&3);
+	 skip=(4-((img->xsize+7)/8)&3)&3;
 	 j=len;
 	 y=img->ysize;
 	 while (j && y--)
@@ -601,11 +646,11 @@ void init_image_bmp(void)
    add_function("encode",img_bmp_encode,
 		"function(object,void|object:string)",0);
    add_function("_decode",img_bmp__decode,
-		"function(string:mapping)",0);
+		"function(string,void|mapping:mapping)",0);
    add_function("decode",img_bmp_decode,
-		"function(string:object)",0);
+		"function(string,void|mapping:object)",0);
    add_function("decode_header",img_bmp_decode_header,
-		"function(string:mapping)",0);
+		"function(string,void|mapping:mapping)",0);
 
    image_bmp_module_program=end_program();
    push_object(clone_object(image_bmp_module_program,0));
-- 
GitLab