diff --git a/src/modules/Image/encodings/pvr.c b/src/modules/Image/encodings/pvr.c index d367f681debc5138e0866121d16fa145fc006872..02628af4f61fe6b322a54b499a3bb57f150823f0 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.1 2000/02/24 01:11:23 marcus Exp $"); +RCSID("$Id: pvr.c,v 1.2 2000/02/27 12:50:44 marcus Exp $"); #include "pike_macros.h" #include "object.h" #include "constants.h" @@ -12,6 +12,7 @@ RCSID("$Id: pvr.c,v 1.1 2000/02/24 01:11:23 marcus Exp $"); #include "svalue.h" #include "threads.h" #include "array.h" +#include "mapping.h" #include "error.h" #include "operators.h" #include "builtin_functions.h" @@ -102,13 +103,107 @@ void image_pvr_f_encode(INT32 args) error("not implemented\n"); } +static void pvr_decode_rect(INT32 attr, unsigned char *src, rgb_group *dst, + INT32 stride, unsigned int h, unsigned int w) +{ + INT32 cnt = h * w; + switch(attr&0xff) { + case MODE_ARGB1555: + case MODE_RGB555: + while(cnt--) { + unsigned int p = src[0]|(src[1]<<8); + dst->r = ((p&0x7c00)>>7)|((p&0x7000)>>12); + dst->g = ((p&0x03e0)>>2)|((p&0x0380)>>7); + dst->b = ((p&0x001f)<<3)|((p&0x001c)>>2); + src+=2; + dst++; + } + break; + case MODE_RGB565: + while(cnt--) { + unsigned int p = src[0]|(src[1]<<8); + dst->r = ((p&0xf800)>>8)|((p&0xe000)>>13); + dst->g = ((p&0x07e0)>>3)|((p&0x0600)>>9); + dst->b = ((p&0x001f)<<3)|((p&0x001c)>>2); + src+=2; + dst++; + } + break; + case MODE_ARGB4444: + while(cnt--) { + unsigned int p = src[0]|(src[1]<<8); + dst->r = ((p&0x0f00)>>4)|((p&0x0f00)>>8); + dst->g = (p&0x00f0)|((p&0x00f0)>>4); + dst->b = ((p&0x000f)<<4)|(p&0x000f); + src+=2; + dst++; + } + break; + } +} + +static void pvr_decode_twiddled(INT32 attr, unsigned char *s, rgb_group *dst, + INT32 stride, unsigned int sz) +{ + unsigned int x, y; + unsigned char *src; + switch(attr&0xff) { + case MODE_ARGB1555: + case MODE_RGB555: + for(y=0; y<sz; y++) { + for(x=0; x<sz; x++) { + unsigned int p; + src = s+(((twiddletab[x]<<1)|twiddletab[y])<<1); + p = src[0]|(src[1]<<8); + dst->r = ((p&0x7c00)>>7)|((p&0x7000)>>12); + dst->g = ((p&0x03e0)>>2)|((p&0x0380)>>7); + dst->b = ((p&0x001f)<<3)|((p&0x001c)>>2); + src+=2; + dst++; + } + dst += stride; + } + break; + case MODE_RGB565: + for(y=0; y<sz; y++) { + for(x=0; x<sz; x++) { + unsigned int p; + src = s+(((twiddletab[x]<<1)|twiddletab[y])<<1); + p = src[0]|(src[1]<<8); + dst->r = ((p&0xf800)>>8)|((p&0xe000)>>13); + dst->g = ((p&0x07e0)>>3)|((p&0x0600)>>9); + dst->b = ((p&0x001f)<<3)|((p&0x001c)>>2); + src+=2; + dst++; + } + dst += stride; + } + break; + case MODE_ARGB4444: + for(y=0; y<sz; y++) { + for(x=0; x<sz; x++) { + unsigned int p; + src = s+(((twiddletab[x]<<1)|twiddletab[y])<<1); + p = src[0]|(src[1]<<8); + dst->r = ((p&0x0f00)>>4)|((p&0x0f00)>>8); + dst->g = (p&0x00f0)|((p&0x00f0)>>4); + dst->b = ((p&0x000f)<<4)|(p&0x000f); + src+=2; + dst++; + } + dst += stride; + } + break; + } +} + void img_pvr_decode(INT32 args,int header_only) { struct pike_string *str; unsigned char *s; int n = 0; INT32 len, attr; - unsigned int h, w, x, y; + unsigned int h, w, x; get_all_args("Image.PVR._decode", args, "%S", &str); s=(unsigned char *)str->str; @@ -160,9 +255,6 @@ void img_pvr_decode(INT32 args,int header_only) int twiddle=0, hasalpha=0, bpp=0; struct object *o; struct image *img; - unsigned char *src = s; - rgb_group *dst; - INT32 cnt; switch(attr&0xff00) { case MODE_TWIDDLE: @@ -174,7 +266,11 @@ void img_pvr_decode(INT32 args,int header_only) case MODE_STRIDE: break; case MODE_TWIDDLED_RECTANGLE: - error("twiddled rectangle not supported\n"); + twiddle = 1; + if((w<h && (w<8 || w>1024 || (w&(w-1)) || h%w)) || + (h>=w && (h<8 || h>1024 || (h&(h-1)) || w%h))) + error("invalid size for twiddle rectangle texture\n"); + break; case MODE_COMPRESSED: case MODE_COMPRESSED_MIPMAP: error("compressed PVRs not supported\n"); @@ -204,7 +300,7 @@ void img_pvr_decode(INT32 args,int header_only) error("unknown PVR color mode\n"); } - if(len < bpp*(cnt = h*w)) + if(len < (INT32)bpp*h*w) error("short PVRT chunk\n"); push_text("image"); @@ -212,7 +308,6 @@ void img_pvr_decode(INT32 args,int header_only) push_int(h); o=clone_object(image_program,2); img=(struct image*)get_storage(o,image_program); - dst=img->img; push_object(o); n++; @@ -220,83 +315,14 @@ void img_pvr_decode(INT32 args,int header_only) init_twiddletab(); if(twiddle) - switch(attr&0xff) { - case MODE_ARGB1555: - case MODE_RGB555: - for(y=0; y<h; y++) - for(x=0; x<w; x++) { - unsigned int p; - src = s+(((twiddletab[x]<<1)|twiddletab[y])<<1); - p = src[0]|(src[1]<<8); - dst->r = ((p&0x7c00)>>7)|((p&0x7000)>>12); - dst->g = ((p&0x03e0)>>2)|((p&0x0380)>>7); - dst->b = ((p&0x001f)<<3)|((p&0x001c)>>2); - src+=2; - dst++; - } - break; - case MODE_RGB565: - for(y=0; y<h; y++) - for(x=0; x<w; x++) { - unsigned int p; - src = s+(((twiddletab[x]<<1)|twiddletab[y])<<1); - p = src[0]|(src[1]<<8); - dst->r = ((p&0xf800)>>8)|((p&0xe000)>>13); - dst->g = ((p&0x07e0)>>3)|((p&0x0600)>>9); - dst->b = ((p&0x001f)<<3)|((p&0x001c)>>2); - src+=2; - dst++; - } - break; - case MODE_ARGB4444: - for(y=0; y<h; y++) - for(x=0; x<w; x++) { - unsigned int p; - src = s+(((twiddletab[x]<<1)|twiddletab[y])<<1); - p = src[0]|(src[1]<<8); - dst->r = ((p&0x0f00)>>4)|((p&0x0f00)>>8); - dst->g = (p&0x00f0)|((p&0x00f0)>>4); - dst->b = ((p&0x000f)<<4)|(p&0x000f); - src+=2; - dst++; - } - break; - } + if(h<w) + for(x=0; x<w; x+=h) + pvr_decode_twiddled(attr, s+bpp*h*x, img->img+x, w-h, h); + else + for(x=0; x<h; x+=w) + pvr_decode_twiddled(attr, s+bpp*w*x, img->img+w*x, 0, w); else - switch(attr&0xff) { - case MODE_ARGB1555: - case MODE_RGB555: - while(cnt--) { - unsigned int p = src[0]|(src[1]<<8); - dst->r = ((p&0x7c00)>>7)|((p&0x7000)>>12); - dst->g = ((p&0x03e0)>>2)|((p&0x0380)>>7); - dst->b = ((p&0x001f)<<3)|((p&0x001c)>>2); - src+=2; - dst++; - } - break; - case MODE_RGB565: - while(cnt--) { - unsigned int p = src[0]|(src[1]<<8); - dst->r = ((p&0xf800)>>8)|((p&0xe000)>>13); - dst->g = ((p&0x07e0)>>3)|((p&0x0600)>>9); - dst->b = ((p&0x001f)<<3)|((p&0x001c)>>2); - src+=2; - dst++; - } - break; - case MODE_ARGB4444: - while(cnt--) { - unsigned int p = src[0]|(src[1]<<8); - dst->r = ((p&0x0f00)>>4)|((p&0x0f00)>>8); - dst->g = (p&0x00f0)|((p&0x00f0)>>4); - dst->b = ((p&0x000f)<<4)|(p&0x000f); - src+=2; - dst++; - } - break; - } - + pvr_decode_rect(attr, s, img->img, 0, h, w); } f_aggregate_mapping(2*n);