diff --git a/src/modules/Image/encodings/x.c b/src/modules/Image/encodings/x.c index fe184f43f3c76893ca79e99cdc909defb79f3e75..47e0fdc595581278547005a0a56d28928fef3b51 100644 --- a/src/modules/Image/encodings/x.c +++ b/src/modules/Image/encodings/x.c @@ -1,9 +1,9 @@ -/* $Id: x.c,v 1.20 1999/05/03 21:17:32 mirar Exp $ */ +/* $Id: x.c,v 1.21 1999/05/20 14:08:56 mirar Exp $ */ /* **! module Image **! note -**! $Id: x.c,v 1.20 1999/05/03 21:17:32 mirar Exp $ +**! $Id: x.c,v 1.21 1999/05/20 14:08:56 mirar Exp $ **! submodule X **! **! This submodule handles encoding and decoding of @@ -29,7 +29,7 @@ #include <winsock.h> #endif -RCSID("$Id: x.c,v 1.20 1999/05/03 21:17:32 mirar Exp $"); +RCSID("$Id: x.c,v 1.21 1999/05/20 14:08:56 mirar Exp $"); #include "pike_macros.h" #include "object.h" #include "constants.h" @@ -780,6 +780,7 @@ static void image_x_decode_truecolor(INT32 args) int i; INT32 n; rgb_group *d; + struct neo_colortable *nct=NULL; if (args<12) error("Image.X.decode_truecolor: too few arguments\n"); @@ -788,7 +789,7 @@ static void image_x_decode_truecolor(INT32 args) if (sp[i-args].type!=T_INT) error("Image.X.decode_truecolor: illegal argument %d\n",i+1); - add_ref(ps=sp[-args].u.string); + ps=sp[-args].u.string; s=(unsigned char*)ps->str; len=ps->len; width=sp[1-args].u.integer; @@ -802,8 +803,26 @@ static void image_x_decode_truecolor(INT32 args) gshift=sp[9-args].u.integer; bbits=sp[10-args].u.integer; bshift=sp[11-args].u.integer; + + if (rshift>=bpp || rshift<0 || + gshift>=bpp || gshift<0 || + bshift>=bpp || bshift<0) + error("Image.X.decode_truecolor: illegal colorshifts\n"); - pop_n_elems(args); + if (args>12) + { + if (sp[12-args].type!=T_OBJECT || + !(nct=(struct neo_colortable*) + get_storage(sp[12-args].u.object,image_colortable_program))) + error("Image.X.decode_truecolor: illegal argument 13, expected colortable\n"); + if (nct->type!=NCT_FLAT) + error("Image.X.decode_truecolor: illegal argument 13, expected colortable in flat mode\n"); + + if (nct->u.flat.numentries<(1<<rbits) || + nct->u.flat.numentries<(1<<gbits) || + nct->u.flat.numentries<(1<<bbits)) + error("Image.X.decode_truecolor: colortable too small\n"); + } if (bbits==8 && rbits==8 && gbits==8 && !((rshift|gshift|bshift|alignbits|bpp)&7)) @@ -815,11 +834,6 @@ static void image_x_decode_truecolor(INT32 args) struct object *o; struct image *img; - if (rpos>=Bpp || rpos<0 || - gpos>=Bpp || gpos<0 || - bpos>=Bpp || bpos<0) - error("Image.X.decode_truecolor: illegal colorshifts\n"); - if (swapbytes) rpos=Bpp-1-rpos, gpos=Bpp-1-gpos, @@ -832,25 +846,112 @@ static void image_x_decode_truecolor(INT32 args) d=img->img; n=width*height; - while (n--) - { - d->r=s[rpos]; - d->g=s[gpos]; - d->b=s[bpos]; - d++; - if (n && (unsigned long)Bpp>=len) - break; - len-=Bpp; - s+=Bpp; - } + if (nct) + while (n--) + { + d->r=nct->u.flat.entries[s[rpos]].color.r; + d->g=nct->u.flat.entries[s[gpos]].color.g; + d->b=nct->u.flat.entries[s[bpos]].color.b; + d++; + + if (n && (unsigned long)Bpp>=len) + break; + len-=Bpp; + s+=Bpp; + } + else + while (n--) + { + d->r=s[rpos]; + d->g=s[gpos]; + d->b=s[bpos]; + d++; + + if (n && (unsigned long)Bpp>=len) + break; + len-=Bpp; + s+=Bpp; + } - free_string(ps); + pop_n_elems(args); + push_object(o); + } + else if (bpp==16 && !(alignbits&15)) + { + struct object *o; + struct image *img; + int rmask=(1<<rbits)-1; + int gmask=(1<<rbits)-1; + int bmask=(1<<rbits)-1; + + push_int(width); + push_int(height); + o=clone_object(image_program,2); + img=(struct image*)get_storage(o,image_program); + + if (nct) + { + d=img->img; + n=width*height; + while (n-- && len>=2) + { + int x; + if (swapbytes) + x=s[1]+(((int)s[0])<<8); + else + x=s[0]+(((int)s[1])<<8); + + d->r=nct->u.flat.entries[(x>>rshift)&rmask].color.r; + d->g=nct->u.flat.entries[(x>>gshift)&gmask].color.g; + d->b=nct->u.flat.entries[(x>>bshift)&bmask].color.b; + d++; + + len-=2; + s+=2; + } + } + else + { + int i,j; + COLORTYPE *rtbl=alloca(1<<rbits); + COLORTYPE *gtbl=alloca(1<<gbits); + COLORTYPE *btbl=alloca(1<<bbits); + if (!rtbl || !gtbl || !btbl) + resource_error(NULL,0,0,"memory",(1<<rbits)+(1<<rbits)+(1<<rbits), + "Out of memory.\n"); + + for (j=0,i=24-rbits; i>0; i-=rbits) j+=1<<i; + for (i=0; i<(1<<rbits); i++) rtbl[i]=(j*i)>>16; + for (j=0,i=24-gbits; i>0; i-=gbits) j+=1<<i; + for (i=0; i<(1<<gbits); i++) gtbl[i]=(j*i)>>16; + for (j=0,i=24-bbits; i>0; i-=bbits) j+=1<<i; + for (i=0; i<(1<<bbits); i++) btbl[i]=(j*i)>>16; + + d=img->img; + n=width*height; + while (n-- && len>=2) + { + int x; + if (swapbytes) + x=s[1]+(((int)s[0])<<8); + else + x=s[0]+(((int)s[1])<<8); + + d->r=rtbl[(x>>rshift)&rmask]; + d->g=gtbl[(x>>gshift)&gmask]; + d->b=btbl[(x>>bshift)&bmask]; + d++; + + len-=2; + s+=2; + } + } + pop_n_elems(args); push_object(o); } else { - free_string(ps); error("Image.X.decode_truecolor: currently not supported non-byte ranges\n"); } }