From 17407a1cd482d087e2fa3b239353b3928cf59a15 Mon Sep 17 00:00:00 2001 From: "Mirar (Pontus Hagland)" <pike@sort.mirar.org> Date: Sun, 11 Apr 1999 14:55:43 +0200 Subject: [PATCH] bmp decode added (and some helper functions) Rev: src/modules/Image/colortable.c:1.61 Rev: src/modules/Image/colortable.h:1.17 Rev: src/modules/Image/encodings/bmp.c:1.2 --- src/modules/Image/colortable.c | 81 ++++++- src/modules/Image/colortable.h | 6 +- src/modules/Image/encodings/bmp.c | 354 +++++++++++++++++++++++++++--- 3 files changed, 401 insertions(+), 40 deletions(-) diff --git a/src/modules/Image/colortable.c b/src/modules/Image/colortable.c index 6f97a095ac..cf0d976eef 100644 --- a/src/modules/Image/colortable.c +++ b/src/modules/Image/colortable.c @@ -1,12 +1,12 @@ #include "global.h" #include <config.h> -/* $Id: colortable.c,v 1.60 1999/04/10 05:18:18 mirar Exp $ */ +/* $Id: colortable.c,v 1.61 1999/04/11 12:55:40 mirar Exp $ */ /* **! module Image **! note -**! $Id: colortable.c,v 1.60 1999/04/10 05:18:18 mirar Exp $ +**! $Id: colortable.c,v 1.61 1999/04/11 12:55:40 mirar Exp $ **! class colortable **! **! This object keeps colortable information, @@ -21,7 +21,7 @@ #undef COLORTABLE_DEBUG #undef COLORTABLE_REDUCE_DEBUG -RCSID("$Id: colortable.c,v 1.60 1999/04/10 05:18:18 mirar Exp $"); +RCSID("$Id: colortable.c,v 1.61 1999/04/11 12:55:40 mirar Exp $"); #include <math.h> /* fabs() */ @@ -929,6 +929,54 @@ static struct nct_flat _img_get_flat_from_string(struct pike_string *str) return flat; } +static struct nct_flat _img_get_flat_from_bgr_string(struct pike_string *str) +{ + struct nct_flat flat; + int i; + + flat.numentries=str->len/3; + if (flat.numentries<1) + error("Can't make a colortable with less then one (1) color.\n"); + + flat.entries=(struct nct_flat_entry*) + xalloc(flat.numentries*sizeof(struct nct_flat_entry)); + + for (i=0; i<flat.numentries; i++) + { + flat.entries[i].color.r=str->str[i*3+2]; + flat.entries[i].color.g=str->str[i*3+1]; + flat.entries[i].color.b=str->str[i*3]; + flat.entries[i].weight=1; + flat.entries[i].no=i; + } + + return flat; +} + +static struct nct_flat _img_get_flat_from_bgrz_string(struct pike_string *str) +{ + struct nct_flat flat; + int i; + + flat.numentries=str->len/4; + if (flat.numentries<1) + error("Can't make a colortable with less then one (1) color.\n"); + + flat.entries=(struct nct_flat_entry*) + xalloc(flat.numentries*sizeof(struct nct_flat_entry)); + + for (i=0; i<flat.numentries; i++) + { + flat.entries[i].color.r=str->str[i*4+2]; + flat.entries[i].color.g=str->str[i*4+1]; + flat.entries[i].color.b=str->str[i*4]; + flat.entries[i].weight=1; + flat.entries[i].no=i; + } + + return flat; +} + static INLINE void _find_cube_dist(struct nct_cube cube,rgb_group rgb, int *dist,int *no, rgbl_group sf) @@ -2150,7 +2198,28 @@ static void image_colortable_add(INT32 args) } else if (sp[-args].type==T_STRING) { - THIS->u.flat=_img_get_flat_from_string(sp[-args].u.string); + if (args>1) + { + if (sp[1-args].type!=T_INT) + SIMPLE_BAD_ARG_ERROR("Image.colortable",2,"int"); + switch (sp[1-args].u.integer) + { + case 0: /* rgb */ + THIS->u.flat=_img_get_flat_from_string(sp[-args].u.string); + break; + case 1: /* bgr */ + THIS->u.flat=_img_get_flat_from_bgr_string(sp[-args].u.string); + break; + case 2: /* bgrz */ + THIS->u.flat= + _img_get_flat_from_bgrz_string(sp[-args].u.string); + break; + default: + SIMPLE_BAD_ARG_ERROR("Image.colortable",2,"int(0..2)"); + } + } + else + THIS->u.flat=_img_get_flat_from_string(sp[-args].u.string); THIS->type=NCT_FLAT; } else if (sp[-args].type==T_INT) @@ -2432,7 +2501,7 @@ void image_colortable_write_rgb(struct neo_colortable *nct, free(flat.entries); } -void image_colortable_write_rgba(struct neo_colortable *nct, +void image_colortable_write_rgbz(struct neo_colortable *nct, unsigned char *dest) { struct nct_flat flat; @@ -2460,7 +2529,7 @@ void image_colortable_write_rgba(struct neo_colortable *nct, free(flat.entries); } -void image_colortable_write_bgra(struct neo_colortable *nct, +void image_colortable_write_bgrz(struct neo_colortable *nct, unsigned char *dest) { struct nct_flat flat; diff --git a/src/modules/Image/colortable.h b/src/modules/Image/colortable.h index 9d52ebd730..4d95e7e4e4 100644 --- a/src/modules/Image/colortable.h +++ b/src/modules/Image/colortable.h @@ -1,7 +1,7 @@ /* **! module Image **! note -**! $Id: colortable.h,v 1.16 1999/04/10 02:02:05 mirar Exp $ +**! $Id: colortable.h,v 1.17 1999/04/11 12:55:43 mirar Exp $ */ #ifdef PIKE_IMAGE_COLORTABLE_H @@ -195,10 +195,10 @@ int image_colortable_size(struct neo_colortable *nct); void image_colortable_write_rgb(struct neo_colortable *nct, unsigned char *dest); -void image_colortable_write_rgba(struct neo_colortable *nct, +void image_colortable_write_rgbz(struct neo_colortable *nct, unsigned char *dest); -void image_colortable_write_bgra(struct neo_colortable *nct, +void image_colortable_write_bgrz(struct neo_colortable *nct, unsigned char *dest); int image_colortable_initiate_dither(struct neo_colortable *nct, diff --git a/src/modules/Image/encodings/bmp.c b/src/modules/Image/encodings/bmp.c index f6fa096705..cb494b1b3e 100644 --- a/src/modules/Image/encodings/bmp.c +++ b/src/modules/Image/encodings/bmp.c @@ -1,9 +1,9 @@ -/* $Id: bmp.c,v 1.1 1999/03/22 14:35:25 mirar Exp $ */ +/* $Id: bmp.c,v 1.2 1999/04/11 12:55:13 mirar Exp $ */ /* **! module Image **! note -**! $Id: bmp.c,v 1.1 1999/03/22 14:35:25 mirar Exp $ +**! $Id: bmp.c,v 1.2 1999/04/11 12:55:13 mirar Exp $ **! submodule BMP **! **! This submodule keeps the BMP (Windows Bitmap) @@ -30,7 +30,7 @@ #include <ctype.h> #include "stralloc.h" -RCSID("$Id: bmp.c,v 1.1 1999/03/22 14:35:25 mirar Exp $"); +RCSID("$Id: bmp.c,v 1.2 1999/04/11 12:55:13 mirar Exp $"); #include "pike_macros.h" #include "object.h" #include "constants.h" @@ -38,6 +38,7 @@ RCSID("$Id: bmp.c,v 1.1 1999/03/22 14:35:25 mirar Exp $"); #include "svalue.h" #include "threads.h" #include "array.h" +#include "mapping.h" #include "error.h" @@ -94,7 +95,7 @@ static INLINE unsigned long _int_from_16bit(unsigned char *data) **! arg object colortable **! Colortable object. **! -** see also: decode +**! see also: decode **! **! returns the encoded image as a string **! @@ -104,19 +105,19 @@ static INLINE unsigned long _int_from_16bit(unsigned char *data) void img_bmp_encode(INT32 args) { - struct object *o,*oc; - struct image *img; - struct neo_colortable *nct; - int n=0,bpp; + struct object *o=NULL,*oc=NULL; + struct image *img=NULL; + struct neo_colortable *nct=NULL; + int n=0,bpp=0; int size,offs; struct pike_string *ps; if (!args) - error("Image.BMP.encode: Illegal number of arguments\n"); + SIMPLE_TOO_FEW_ARGS_ERROR("Image.BMP.encode",1); if (sp[-args].type!=T_OBJECT || !(img=(struct image*)get_storage(o=sp[-args].u.object,image_program))) - error("Image.BMP.encode: Illegal argument 1, expected image object\n"); + SIMPLE_BAD_ARG_ERROR("Image.BMP.encode",1,"image object"); if (args==1) nct=NULL,oc=NULL; @@ -124,16 +125,14 @@ void img_bmp_encode(INT32 args) if (sp[-args].type!=T_OBJECT || !(nct=(struct neo_colortable*) get_storage(oc=sp[1-args].u.object,image_colortable_program))) - error("Image.BMP.encode: Illegal argument 2, " - "expected colortable object\n"); + SIMPLE_BAD_ARG_ERROR("Image.BMP.encode",2,"colortable object"); if (!nct) bpp=24; else if (image_colortable_size(nct)<=256) bpp=8; /* only supports this for now */ else - error("Image.BMP.encode: Illegal argument 2, " - "can only handle less or equal then 256 colors\n"); + SIMPLE_BAD_ARG_ERROR("Image.BMP.encode",2,"colortable object with max 256 colors"); if (oc) oc->refs++; o->refs++; @@ -171,7 +170,7 @@ void img_bmp_encode(INT32 args) { ps=begin_shared_string((1<<bpp)*4); MEMSET(ps->str,0,(1<<bpp)*4); - image_colortable_write_bgra(nct,(unsigned char *)ps->str); + image_colortable_write_bgrz(nct,(unsigned char *)ps->str); push_string(end_shared_string(ps)); n++; } @@ -183,6 +182,7 @@ void img_bmp_encode(INT32 args) if (nct) { + /* 8bpp image */ ps=begin_shared_string(img->xsize*img->ysize); image_colortable_index_8bit_image(nct,img->img,(unsigned char *)ps->str, img->xsize*img->ysize,img->xsize); @@ -191,24 +191,18 @@ void img_bmp_encode(INT32 args) } else { - if (sizeof(rgb_group)==3) - push_string(make_shared_binary_string((char*)img->img, - img->xsize*img->ysize*3)); - else + unsigned char *c; + int n=img->xsize*img->ysize; + rgb_group *s=img->img; + c=(unsigned char*)((ps=begin_shared_string(n*3))->str); + while (n--) { - unsigned char *c; - int n=img->xsize*img->ysize; - rgb_group *s=img->img; - c=(unsigned char*)((ps=begin_shared_string(n*3))->str); - while (n--) - { - *(c++)=s->r; - *(c++)=s->g; - *(c++)=s->b; - s++; - } - push_string(end_shared_string(ps)); + *(c++)=s->b; + *(c++)=s->g; + *(c++)=s->r; + s++; } + push_string(end_shared_string(ps)); n++; } @@ -239,6 +233,298 @@ void img_bmp_encode(INT32 args) pop_stack(); /* get rid of colortable & source objects */ } +/* +**! method mapping _decode(string data) +**! method mapping decode_header(string data) +**! method object decode(string data) +**! Decode a BMP. Not all modes are supported. +**! +**! <ref>decode</ref> gives an image object, +**! <ref>_decode</ref> gives a mapping in the format +**! <pre> +**! "type":"image/bmp", +**! "image":image object, +**! "colortable":colortable object (if applicable) +**! +**! "xsize":int, +**! "ysize":int, +**! "compression":int, +**! "bpp":int, +**! "windows":int, +**! </pre> +**! +**! see also: encode +**! +**! returns the encoded image as a string +**! +**! bugs +**! Doesn't support all BMP modes. At all. +*/ + +void i_img_bmp__decode(INT32 args,int header_only) +{ + p_wchar0 *s; + int len; + int xsize=0,ysize=0,bpp=0,comp=0; + struct image *img=NULL; + struct neo_colortable *nct=NULL; + struct object *o; + rgb_group *d; + int n=0,j,i,y,skip; + int windows=0; + + if (args<1) + SIMPLE_TOO_FEW_ARGS_ERROR("Image.BMP.decode",1); + + if (sp[-args].type!=T_STRING) + SIMPLE_BAD_ARG_ERROR("Image.BMP.decode",1,"string"); + if (sp[-args].u.string->size_shift) + SIMPLE_BAD_ARG_ERROR("Image.BMP.decode",1,"8 bit string"); + + s=(p_wchar0*)sp[-args].u.string->str; + len=sp[-args].u.string->len; + + pop_n_elems(args-1); + + if (len<20) + error("Image.BMP.decode: not a BMP (file to short)\n"); + + if (s[0]!='B' || s[1]!='M') + error("Image.BMP.decode: not a BMP (illegal header)\n"); + + /* ignore stupid info like file size */ + + switch (int_from_32bit(s+14)) + { + case 40: /* windows mode */ + + if (len<54) + error("Image.BMP.decode: unexpected EOF in header\n"); + + push_text("xsize"); + push_int(xsize=int_from_32bit(s+14+4*1)); + n++; + + push_text("ysize"); + push_int(ysize=int_from_32bit(s+14+4*2)); + n++; + + push_text("target_planes"); + push_int(int_from_16bit(s+14+4*3)); + n++; + + push_text("bpp"); + push_int(bpp=int_from_16bit(s+14+4*3+2)); + n++; + + push_text("compression"); + push_int(comp=int_from_32bit(s+14+4*4)); + n++; + + push_text("xres"); + push_int(int_from_32bit(s+14+4*5)); + n++; + + push_text("yres"); + push_int(int_from_32bit(s+14+4*6)); + n++; + + push_text("windows"); + push_int(windows=1); + n++; + + s+=54; + len-=54; + + break; + + case 12: /* dos (?) mode */ + + if (len<26) + error("Image.BMP.decode: unexpected EOF in header\n"); + + push_text("xsize"); + push_int(xsize=int_from_16bit(s+14+4)); + n++; + + push_text("ysize"); + push_int(ysize=int_from_16bit(s+14+6)); + n++; + + push_text("target_planes"); + push_int(int_from_16bit(s+14+8)); + n++; + + push_text("bpp"); + push_int(bpp=int_from_16bit(s+14+10)); + n++; + + push_text("compression"); + push_int(comp=0); + n++; + + s+=26; + len-=26; + + break; + + default: + error("Image.BMP.decode: not a BMP (illegal info)\n"); + } + + if (header_only) + { + f_aggregate_mapping(n*2); + stack_swap(); + pop_stack(); + return; + } + + if (bpp!=24) /* get palette */ + { + push_text("colortable"); + + if (windows) + { + if ((4<<bpp)>len) + error("Image.BMP.decode: unexpected EOF in palette\n"); + + push_string(make_shared_binary_string(s,(4<<bpp))); + push_int(2); + push_object(o=clone_object(image_colortable_program,2)); + nct=(struct neo_colortable*)get_storage(o,image_colortable_program); + + s+=(4<<bpp); + len-=(4<<bpp); + } + else + { + if ((3<<bpp)>len) + error("Image.BMP.decode: unexpected EOF in palette\n"); + + push_string(make_shared_binary_string(s,(3<<bpp))); + push_int(1); + push_object(o=clone_object(image_colortable_program,2)); + nct=(struct neo_colortable*)get_storage(o,image_colortable_program); + + s+=(3<<bpp); + len-=(3<<bpp); + } + } + + push_text("image"); + + push_int(xsize); + push_int(ysize); + push_object(o=clone_object(image_program,2)); + img=(struct image*)get_storage(o,image_program); + n++; + + if (comp) + error("Image.BMP.decode: can't handle compressed BMP\n"); + + switch (bpp) + { + case 24: + j=(len)/3; + y=img->ysize; + while (j && y--) + { + d=img->img+img->xsize*y; + i=img->xsize; if (i>j) i=j; + j-=i; + while (i--) + { + d->b=*(s++); + d->g=*(s++); + d->r=*(s++); + d++; + } + } + break; + case 8: + skip=4-(img->xsize&3); + j=len; + y=img->ysize; + while (j && y--) + { + d=img->img+img->xsize*y; + i=img->xsize; if (i>j) i=j; + j-=i; + while (i--) + *(d++)=nct->u.flat.entries[*(s++)].color; + if (j>=skip) { j-=skip; s+=skip; } + } + break; + case 4: + skip=3-((img->xsize/2)&3); + j=len; + y=img->ysize; + while (j && y--) + { + d=img->img+img->xsize*y; + i=img->xsize; + while (i && j--) + { + if (i) *(d++)=nct->u.flat.entries[(s[0]>>4)&15].color,i--; + if (i) *(d++)=nct->u.flat.entries[s[0]&15].color,i--; + s++; + } + if (j>=skip) { j-=skip; s+=skip; } + } + break; + case 1: + skip=3-((img->xsize/8)&3); + j=len; + y=img->ysize; + while (j && y--) + { + d=img->img+img->xsize*y; + i=img->xsize; + while (i && j--) + { + if (i) *(d++)=nct->u.flat.entries[!!(s[0]&128)].color,i--; + if (i) *(d++)=nct->u.flat.entries[!!(s[0]&64)].color,i--; + if (i) *(d++)=nct->u.flat.entries[!!(s[0]&32)].color,i--; + if (i) *(d++)=nct->u.flat.entries[!!(s[0]&16)].color,i--; + if (i) *(d++)=nct->u.flat.entries[!!(s[0]&8)].color,i--; + if (i) *(d++)=nct->u.flat.entries[!!(s[0]&4)].color,i--; + if (i) *(d++)=nct->u.flat.entries[!!(s[0]&2)].color,i--; + if (i) *(d++)=nct->u.flat.entries[s[0]&1].color,i--; + s++; + } + if (j>=skip) { j-=skip; s+=skip; } + } + break; + default: + error("Image.BMP.decode: unknown bpp: %d\n",bpp); + } + + f_aggregate_mapping(n*2); + stack_swap(); + pop_stack(); +} + + +void img_bmp__decode(INT32 args) +{ + return i_img_bmp__decode(args,0); +} + +void img_bmp_decode_header(INT32 args) +{ + return i_img_bmp__decode(args,1); +} + +void f_index(INT32); + +void img_bmp_decode(INT32 args) +{ + img_bmp__decode(args); + push_text("image"); + f_index(2); +} + struct program *image_bmp_module_program=NULL; void init_image_bmp(void) @@ -247,6 +533,12 @@ 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); + add_function("ddecode",img_bmp_decode, + "function(string:object)",0); + add_function("decode_header",img_bmp_decode_header, + "function(string:mapping)",0); image_bmp_module_program=end_program(); push_object(clone_object(image_bmp_module_program,0)); -- GitLab