diff --git a/src/modules/Image/encodings/tim.c b/src/modules/Image/encodings/tim.c index 96345d58bdea9d5d15aa0fd99b8b446d065d3b88..3d7da88883632938cce54161366b6d3dd15acbf4 100644 --- a/src/modules/Image/encodings/tim.c +++ b/src/modules/Image/encodings/tim.c @@ -4,7 +4,7 @@ #include <ctype.h> #include "stralloc.h" -RCSID("$Id: tim.c,v 1.2 2000/03/21 15:52:20 peter Exp $"); +RCSID("$Id: tim.c,v 1.3 2000/03/22 16:59:14 peter Exp $"); #include "pike_macros.h" #include "object.h" #include "constants.h" @@ -34,9 +34,6 @@ extern struct program *image_program; **! It is a simple, uncompressed, truecolor or CLUT format. */ -//FIXME: Add to ANY. -//FIXME: header_only doesn't get the width and height. - /* **! method object decode(string data) **! method object decode_alpha(string data) @@ -66,7 +63,8 @@ extern struct program *image_program; #define FLAG_CLUT 8 static void tim_decode_rect(INT32 attr, unsigned char *src, rgb_group *dst, - INT32 stride, unsigned int h, unsigned int w) + unsigned char *clut, unsigned int h, + unsigned int w) { INT32 cnt = h * w; switch(attr&7) { @@ -80,18 +78,48 @@ static void tim_decode_rect(INT32 attr, unsigned char *src, rgb_group *dst, dst++; } break; + case MODE_CLUT4: + cnt = cnt/2; + while(cnt--) { + int i, cluti = (src[0]&0xf)*2; + unsigned int p; + + for(i=0; i<2; i++) + { + p = clut[cluti]|(clut[cluti+1]<<8); + dst->b = ((p&0x7c00)>>7)|((p&0x7000)>>12); + dst->g = ((p&0x03e0)>>2)|((p&0x0380)>>7); + dst->r = ((p&0x001f)<<3)|((p&0x001c)>>2); + dst++; + cluti = (src[0]>>4)*2; + } + src++; + } + break; + case MODE_CLUT8: + while(cnt--) { + int i, cluti = (src[0])*2; + unsigned int p = clut[cluti]|(clut[cluti+1]<<8); + + dst->b = ((p&0x7c00)>>7)|((p&0x7000)>>12); + dst->g = ((p&0x03e0)>>2)|((p&0x0380)>>7); + dst->r = ((p&0x001f)<<3)|((p&0x001c)>>2); + dst++; + src++; + } + break; } } -static void pvr_decode_alpha_rect(INT32 attr, unsigned char *src, - rgb_group *dst, INT32 stride, +static void tim_decode_alpha_rect(INT32 attr, unsigned char *src, + rgb_group *dst, unsigned char *clut, unsigned int h, unsigned int w) { INT32 cnt = h * w; switch(attr&7) { case MODE_DC15: while(cnt--) { - if(src[1]&0x80) + if(!(src[1]>>15)) dst->b = dst->g = dst->r = ~0; else dst->b = dst->g = dst->r = 0; @@ -99,110 +127,179 @@ static void pvr_decode_alpha_rect(INT32 attr, unsigned char *src, dst++; } break; + case MODE_CLUT4: + cnt = cnt/2; + while(cnt--) { + if(!(clut[(src[1]&0xf)*2]>>15)) + dst->b = dst->g = dst->r = ~0; + else + dst->b = dst->g = dst->r = 0; + dst++; + if(!(clut[(src[1]>>4)*2]>>15)) + dst->b = dst->g = dst->r = ~0; + else + dst->b = dst->g = dst->r = 0; + src++; + dst++; + } + break; + case MODE_CLUT8: + while(cnt--) { + if(!(clut[(src[1])*2]>>15)) + dst->b = dst->g = dst->r = ~0; + else + dst->b = dst->g = dst->r = 0; + src++; + dst++; + } + break; } } void img_tim_decode(INT32 args, int header_only) { - struct pike_string *str; - unsigned char *s; - int n=0, hasalpha=0, bpp=0; - INT32 len, attr, bsize; - unsigned int h, w, x; - - get_all_args("Image.TIM._decode", args, "%S", &str); - s=(unsigned char *)str->str; - len=str->len; - pop_n_elems(args-1); - - if(len < 12 || (s[0] != 0x10 || s[2] != 0 || s[3] != 0)) - error("not a TIM texture\n"); - else if(s[2] != 0) - error("unknown version of TIM texture\n"); - - push_text("type"); - push_text("image/x-tim"); - n++; - - attr = s[4]|(s[5]<<8)|(s[6]<<16)|(s[7]<<24); - if(attr&0xfffffff0) - error("unknown flags in TIM texture\n"); - - push_text("attr"); - push_int(attr); - n++; - - /* note: bsize if bogus when no clut i used. */ - bsize = s[8]|(s[9]<<8)|(s[10]<<16)|(s[11]<<24); - printf("bsize: %d\n", bsize); - - if(attr&FLAG_CLUT) - error("TIM with CLUT not supported\n"); - - switch(attr&7) { - case MODE_DC15: - //dx and dy word ignored - w = s[16]|(s[17]<<8); - h = s[18]|(s[19]<<8); - bpp = 2; - hasalpha = 1; - s += 20; - len -= 20; - break; - case MODE_DC24: - error("24bit TIMs not supported\n"); - case MODE_CLUT4: - case MODE_CLUT8: - error("palette TIMs not supported\n"); - case MODE_MIXED: - error("mixed TIMs not supported\n"); - default: - error("unknown TIM format\n"); - } - - push_text("xsize"); - push_int(w); - n++; - push_text("ysize"); - push_int(h); - n++; - printf("w: %d, h: %d\n", w, h); - - if(!header_only) { - struct object *o; - struct image *img; - INT32 clut=0; - - if(len < (INT32)(bpp*(h*w))) - error("short pixel data\n"); - - push_text("image"); - push_int(w); - push_int(h); - o=clone_object(image_program,2); - img=(struct image*)get_storage(o,image_program); - push_object(o); - n++; - - tim_decode_rect(attr, s, img->img, 0, h, w); - - if(hasalpha) { - push_text("alpha"); - push_int(w); - push_int(h); - o=clone_object(image_program,2); - img=(struct image*)get_storage(o,image_program); - push_object(o); - n++; - - pvr_decode_alpha_rect(attr, s, img->img, 0, h, w); - } - } + struct pike_string *str; + unsigned char *s, *clut; + int n=0, hasalpha=0, bitpp=0, bsize=0; + INT32 len, attr; + unsigned int h, w, i; + + get_all_args("Image.TIM._decode", args, "%S", &str); + clut=s=(unsigned char *)str->str; + clut+=20; + len=str->len; + pop_n_elems(args-1); + + if(len < 12 || (s[0] != 0x10 || s[2] != 0 || s[3] != 0)) + error("not a TIM texture\n"); + else if(s[2] != 0) + error("unknown version of TIM texture\n"); + + s += 4; len -= 4; + + push_text("type"); + push_text("image/x-tim"); + n++; + + attr = s[0]|(s[1]<<8)|(s[2]<<16)|(s[3]<<24); + if(attr&0xfffffff0) + error("unknown flags in TIM texture\n"); + + s += 4; len -= 4; - f_aggregate_mapping(2*n); + push_text("attr"); + push_int(attr); + n++; + + if(attr&FLAG_CLUT) { + bsize = s[0]|(s[1]<<8)|(s[2]<<16)|(s[3]<<24); +#ifdef TIM_DEBUG + printf("bsize: %d\n", bsize); +#endif + s += bsize; len -= bsize; + } + + /* FIXME: Unknown what this comes from */ + s += 4; len -= 4; - stack_swap(); - pop_stack(); + switch(attr&7) { + case MODE_DC15: +#ifdef TIM_DEBUG + printf("15bit\n"); + printf("dx: %d, dy: %d\n", s[0]|(s[1]<<8), s[2]|(s[3]<<8)); +#endif + s += 4; len -= 4; + w = s[0]|(s[1]<<8); + h = s[2]|(s[3]<<8); + s += 4; len -= 4; + bitpp = 16; + hasalpha = 1; + break; + case MODE_DC24: +#ifdef TIM_DEBUG + printf("24bit\n"); +#endif + error("24bit TIMs not supported. Please send an example to peter@roxen.com\n"); + case MODE_CLUT4: + //dx and dy word ignored +#ifdef TIM_DEBUG + printf("CLUT4\n"); + printf("dx: %d, dy: %d\n", s[0]|(s[1]<<8), s[2]|(s[3]<<8)); +#endif + s += 4; len -= 4; + w = (s[0]|(s[1]<<8))*4; + h = s[2]|(s[3]<<8); + s += 4; len -= 4; + bitpp = 4; + hasalpha = 1; + break; + case MODE_CLUT8: + //dx and dy word ignored +#ifdef TIM_DEBUG + printf("CLUT8\n"); + printf("dx: %d, dy: %d\n", s[0]|(s[1]<<8), s[2]|(s[3]<<8)); +#endif + s += 4; len -= 4; + w = (s[0]|(s[1]<<8))*2; + h = s[2]|(s[3]<<8); + s += 4; len -= 4; + bitpp = 8; + hasalpha = 1; + break; + case MODE_MIXED: +#ifdef TIM_DEBUG + printf("Mixed\n"); +#endif + error("mixed TIMs not supported\n"); + default: + error("unknown TIM format\n"); + } + + push_text("xsize"); + push_int(w); + n++; + push_text("ysize"); + push_int(h); + n++; + +#ifdef TIM_DEBUG + printf("w: %d, h: %d\n", w, h); +#endif + + if(!header_only) { + struct object *o; + struct image *img; + + if(len < (INT32)(bitpp*(h*w)/8)) + error("short pixel data\n"); + + push_text("image"); + push_int(w); + push_int(h); + o=clone_object(image_program,2); + img=(struct image*)get_storage(o,image_program); + push_object(o); + n++; + + tim_decode_rect(attr, s, img->img, clut, h, w); + + if(hasalpha) { + push_text("alpha"); + push_int(w); + push_int(h); + o=clone_object(image_program,2); + img=(struct image*)get_storage(o,image_program); + push_object(o); + n++; + + tim_decode_alpha_rect(attr, s, img->img, clut, h, w); + } + } + + f_aggregate_mapping(2*n); + + stack_swap(); + pop_stack(); } static void image_tim_f_decode(INT32 args)