diff --git a/src/modules/Image/encodings/pvr.c b/src/modules/Image/encodings/pvr.c index 702b11ba39f105dfcc201f4849ce5d88928eeabe..c0bb57fd0861b25504582833bf254c996309b05a 100644 --- a/src/modules/Image/encodings/pvr.c +++ b/src/modules/Image/encodings/pvr.c @@ -4,7 +4,7 @@ #include <ctype.h> #include "stralloc.h" -RCSID("$Id: pvr.c,v 1.5 2000/02/27 14:48:13 marcus Exp $"); +RCSID("$Id: pvr.c,v 1.6 2000/02/27 16:14:11 marcus Exp $"); #include "pike_macros.h" #include "object.h" #include "constants.h" @@ -100,6 +100,21 @@ static void init_twiddletab() twiddleinited=1; } +static int pvr_check_alpha(struct image *alpha) +{ + int r=0; + INT32 cnt; + rgb_group *p; + if(alpha==NULL) + return 0; + for(cnt=alpha->xsize*alpha->ysize, p=alpha->img; cnt--; p++) + if(p->g < 16) + r=1; + else if(p->g < 240) + return 2; + return r; +} + static void pvr_encode_rect(INT32 attr, rgb_group *src, unsigned char *dst, INT32 stride, unsigned int h, unsigned int w) { @@ -117,6 +132,38 @@ static void pvr_encode_rect(INT32 attr, rgb_group *src, unsigned char *dst, } } +static void pvr_encode_alpha_rect(INT32 attr, rgb_group *src, rgb_group *alpha, + unsigned char *dst, INT32 stride, + unsigned int h, unsigned int w) +{ + INT32 cnt = h * w; + switch(attr&0xff) { + case MODE_ARGB1555: + while(cnt--) { + unsigned int p = + ((src->r&0xf8)<<7)|((src->g&0xf8)<<2)|((src->b&0xf8)>>3); + if(alpha->g&0x80) + p |= 0x8000; + *dst++=p&0xff; + *dst++=(p&0xff00)>>8; + src++; + alpha++; + } + break; + case MODE_ARGB4444: + while(cnt--) { + unsigned int p = + ((alpha->g&0xf0)<<8)| + ((src->r&0xf0)<<4)|(src->g&0xf0)|((src->b&0xf0)>>4); + *dst++=p&0xff; + *dst++=(p&0xff00)>>8; + src++; + alpha++; + } + break; + } +} + void image_pvr_f_encode(INT32 args) { struct object *imgo; @@ -160,7 +207,20 @@ void image_pvr_f_encode(INT32 args) res = begin_shared_string(8+(sz=8+2*img->xsize*img->ysize)+(has_gbix? 12:0)); dst = STR0(res); - attr = MODE_RECTANGLE|MODE_RGB565; + switch(pvr_check_alpha(alpha)) { + case 0: + alpha = NULL; + attr = MODE_RGB565; + break; + case 1: + attr = MODE_ARGB1555; + break; + case 2: + attr = MODE_ARGB4444; + break; + } + + attr |= MODE_RECTANGLE; if(has_gbix) { *dst++ = 'G'; @@ -194,7 +254,11 @@ void image_pvr_f_encode(INT32 args) *dst++ = (img->ysize&0x00ff); *dst++ = (img->ysize&0xff00)>>8; - pvr_encode_rect(attr, img->img, dst, 0, img->ysize, img->xsize); + if(alpha != NULL) + pvr_encode_alpha_rect(attr, img->img, alpha->img, dst, 0, + img->ysize, img->xsize); + else + pvr_encode_rect(attr, img->img, dst, 0, img->ysize, img->xsize); pop_n_elems(args); push_string(end_shared_string(res)); @@ -299,7 +363,7 @@ static void pvr_decode_alpha_rect(INT32 attr, unsigned char *src, switch(attr&0xff) { case MODE_ARGB1555: while(cnt--) { - if(src[1]&0x8000) + if(src[1]&0x80) dst->r = dst->g = dst->b = ~0; else dst->r = dst->g = dst->b = 0;