From 34fab4e276d383d827298f55826e6ad02c275725 Mon Sep 17 00:00:00 2001
From: Marcus Comstedt <marcus@mc.pp.se>
Date: Thu, 24 Feb 2000 02:11:23 +0100
Subject: [PATCH] PowerVR texture image format added.

Rev: lib/modules/_Image.pmod/module.pmod:1.6
Rev: src/modules/Image/encodings/Makefile.in:1.30
Rev: src/modules/Image/encodings/any.c:1.14
Rev: src/modules/Image/encodings/pvr.c:1.1
Rev: src/modules/Image/initstuff.h:1.8
---
 .gitattributes                          |   1 +
 lib/modules/_Image.pmod/module.pmod     |   4 +-
 src/modules/Image/encodings/Makefile.in |   4 +-
 src/modules/Image/encodings/any.c       |  19 +-
 src/modules/Image/encodings/pvr.c       | 347 ++++++++++++++++++++++++
 src/modules/Image/initstuff.h           |   1 +
 6 files changed, 369 insertions(+), 7 deletions(-)
 create mode 100644 src/modules/Image/encodings/pvr.c

diff --git a/.gitattributes b/.gitattributes
index 90d7753a25..8fb372f9d2 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -238,6 +238,7 @@ testfont binary
 /src/modules/Image/encodings/png.c foreign_ident
 /src/modules/Image/encodings/pnm.c foreign_ident
 /src/modules/Image/encodings/psd.c foreign_ident
+/src/modules/Image/encodings/pvr.c foreign_ident
 /src/modules/Image/encodings/ras.c foreign_ident
 /src/modules/Image/encodings/tga.c foreign_ident
 /src/modules/Image/encodings/wbf.c foreign_ident
diff --git a/lib/modules/_Image.pmod/module.pmod b/lib/modules/_Image.pmod/module.pmod
index 3437879e9b..06b5b45a93 100644
--- a/lib/modules/_Image.pmod/module.pmod
+++ b/lib/modules/_Image.pmod/module.pmod
@@ -1,5 +1,5 @@
 //! module Image
-//! $Id: module.pmod,v 1.5 2000/02/08 03:39:46 per Exp $
+//! $Id: module.pmod,v 1.6 2000/02/24 01:11:22 marcus Exp $
 
 //! method object(Image.Image) load()
 //! method object(Image.Image) load(object file)
@@ -58,7 +58,7 @@ mapping _decode( string data, mixed|void tocolor )
 
   if(!i)
     foreach( ({ "XCF", "PSD", "PNG",  "BMP",  "TGA", "PCX",
-                "XBM", "XPM", "TIFF", "ILBM", "PS",
+                "XBM", "XPM", "TIFF", "ILBM", "PS", "PVR",
        /* Image formats low on headers below this mark */
                 "HRZ", "AVS", "WBF",
        /* "XFace" Always succeds*/
diff --git a/src/modules/Image/encodings/Makefile.in b/src/modules/Image/encodings/Makefile.in
index 9b14cd6c8f..37708d2009 100644
--- a/src/modules/Image/encodings/Makefile.in
+++ b/src/modules/Image/encodings/Makefile.in
@@ -1,7 +1,7 @@
-# $Id: Makefile.in,v 1.29 1999/10/22 00:24:37 hubbe Exp $
+# $Id: Makefile.in,v 1.30 2000/02/24 01:11:22 marcus Exp $
 SRCDIR=@srcdir@
 VPATH=@srcdir@:@srcdir@/../../..:../../..
-OBJS = gif.o gif_lzw.o pnm.o x.o xwd.o png.o any.o bmp.o tga.o pcx.o xbm.o _xpm.o ilbm.o iff.o xcf.o hrz.o avs.o psd.o gd.o wbf.o ras.o
+OBJS = gif.o gif_lzw.o pnm.o x.o xwd.o png.o any.o bmp.o tga.o pcx.o xbm.o _xpm.o ilbm.o iff.o xcf.o hrz.o avs.o psd.o gd.o wbf.o ras.o pvr.o
 
 @SET_MAKE@
 
diff --git a/src/modules/Image/encodings/any.c b/src/modules/Image/encodings/any.c
index 58b84416a5..0f468e2dc7 100644
--- a/src/modules/Image/encodings/any.c
+++ b/src/modules/Image/encodings/any.c
@@ -1,9 +1,9 @@
-/* $Id: any.c,v 1.13 1999/10/21 22:39:01 marcus Exp $ */
+/* $Id: any.c,v 1.14 2000/02/24 01:11:22 marcus Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: any.c,v 1.13 1999/10/21 22:39:01 marcus Exp $
+**!	$Id: any.c,v 1.14 2000/02/24 01:11:22 marcus Exp $
 **! submodule ANY
 **!
 **!	This method calls the other decoding methods
@@ -23,7 +23,7 @@
 #include <ctype.h>
 
 #include "stralloc.h"
-RCSID("$Id: any.c,v 1.13 1999/10/21 22:39:01 marcus Exp $");
+RCSID("$Id: any.c,v 1.14 2000/02/24 01:11:22 marcus Exp $");
 #include "pike_macros.h"
 #include "operators.h"
 #include "builtin_functions.h"
@@ -43,6 +43,7 @@ void image_pnm_decode(INT32 args);
 void image_xwd__decode(INT32 args);
 void image_ilbm_decode(INT32 args);
 void image_ras_decode(INT32 args);
+void img_pvr_f_decode_header(INT32 args);
 
 /*
 **! method mapping _decode(string data)
@@ -147,6 +148,12 @@ void image_any__decode(INT32 args)
 	 push_text("image/x-sun-raster");
 	 goto simple_image;
 
+      case CHAR2('P','V'):
+      case CHAR2('G','B'):
+	 /* PVR */
+	 img_pvr_f__decode(1);
+	 return;
+
       case CHAR2(0,0):
 	 switch (CHAR2(sp[-args].u.string->str[2],sp[-args].u.string->str[3]))
 	 {
@@ -251,6 +258,12 @@ void image_any_decode_header(INT32 args)
 	 /* RAS */
 	 error("Image.ANY.decode: decoding of RAS header unimplemented\n");
 
+      case CHAR2('P','V'):
+      case CHAR2('G','B'):
+	 /* PVR */
+	 img_pvr_f_decode_header(1);
+	 return;
+
       case CHAR2(0,0):
 	 switch (CHAR2(sp[-args].u.string->str[2],sp[-args].u.string->str[3]))
 	 {
diff --git a/src/modules/Image/encodings/pvr.c b/src/modules/Image/encodings/pvr.c
new file mode 100644
index 0000000000..d367f681de
--- /dev/null
+++ b/src/modules/Image/encodings/pvr.c
@@ -0,0 +1,347 @@
+#include "global.h"
+#include "image_machine.h"
+#include <math.h>
+#include <ctype.h>
+
+#include "stralloc.h"
+RCSID("$Id: pvr.c,v 1.1 2000/02/24 01:11:23 marcus Exp $");
+#include "pike_macros.h"
+#include "object.h"
+#include "constants.h"
+#include "interpret.h"
+#include "svalue.h"
+#include "threads.h"
+#include "array.h"
+#include "error.h"
+#include "operators.h"
+#include "builtin_functions.h"
+#include "module_support.h"
+
+
+#include "image.h"
+
+extern struct program *image_program;
+
+/*
+**! module Image
+**! submodule PVR
+**!
+**! 	Handle encoding and decoding of PVR images.
+**! 
+**! 	PVR is the texture format of the NEC PowerVR system
+**! 	It is a rather simple, uncompressed, truecolor
+**!     format. 
+*/
+
+/*
+**! method object decode(string data)
+**! method object decode_alpha(string data)
+**! method mapping decode_header(string data)
+**! method mapping _decode(string data)
+**!	decodes a PVR image
+**!
+**!	The <ref>decode_header</ref> and <ref>_decode</ref>
+**!	has these elements:
+**!
+**!	<pre>
+**!        "image":object            - image object    \- not decode_header
+**!	   "alpha":object            - decoded alpha   /
+**!	   
+**!	   "type":"image/x-pvr"      - image type
+**!	   "xsize":int               - horisontal size in pixels
+**!	   "ysize":int               - vertical size in pixels
+**!	   "attr":int		     - texture attributes
+**!	   "global_index":int	     - global index (if present)
+**!	</pre>
+**!	  
+**!
+**! method string encode(object image)
+**! method string encode(object image,mapping options)
+**!	encode a PVR image
+**!
+**!	options is a mapping with optional values:
+**!	<pre>
+**!	   "alpha":object            - alpha channel
+**!	</pre>
+*/
+
+#define MODE_ARGB1555 0x00
+#define MODE_RGB565   0x01
+#define MODE_ARGB4444 0x02
+#define MODE_YUV422   0x03
+#define MODE_BUMPMAP  0x04
+#define MODE_RGB555   0x05
+#define MODE_ARGB8888 0x06
+
+#define MODE_TWIDDLE            0x0100
+#define MODE_TWIDDLE_MIPMAP     0x0200
+#define MODE_COMPRESSED         0x0300
+#define MODE_COMPRESSED_MIPMAP  0x0400
+#define MODE_CLUT4              0x0500
+#define MODE_CLUT4_MIPMAP       0x0600
+#define MODE_CLUT8              0x0700
+#define MODE_CLUT8_MIPMAP       0x0800
+#define MODE_RECTANGLE          0x0900
+#define MODE_STRIDE             0x0b00
+#define MODE_TWIDDLED_RECTANGLE 0x0d00
+
+static INT32 twiddletab[1024];
+static int twiddleinited=0;
+
+static void init_twiddletab()
+{
+  int x;
+  for(x=0; x<1024; x++)
+    twiddletab[x] = (x&1)|((x&2)<<1)|((x&4)<<2)|((x&8)<<3)|((x&16)<<4)|
+      ((x&32)<<5)|((x&64)<<6)|((x&128)<<7)|((x&256)<<8)|((x&512)<<9);
+  twiddleinited=1;
+}
+
+void image_pvr_f_encode(INT32 args)
+{
+   error("not implemented\n");
+}
+
+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;
+
+   get_all_args("Image.PVR._decode", args, "%S", &str);
+   s=(unsigned char *)str->str;
+   len=str->len;
+   pop_n_elems(args-1);
+
+   if(len >= 12 && !strncmp(s, "GBIX", 4) &&
+      s[4]==4 && s[5]==0 && s[6]==0 && s[7]==0) {
+     push_text("global_index");
+     push_int(s[8]|(s[9]<<8)|(s[10]<<16)|(s[11]<<24));
+     n++;
+     len -= 12;
+     s += 12;
+   }
+
+   if(len < 16 || strncmp(s, "PVRT", 4))
+     error("not a PVR texture\n");
+   else {
+     INT32 l = s[4]|(s[5]<<8)|(s[6]<<16)|(s[7]<<24);
+     if(l+8>len)
+       error("file is truncated\n");
+     else if(l<8)
+       error("invalid PVRT chunk length\n");
+     len = l+8;
+   }
+
+   push_text("type");
+   push_text("image/x-pvr");
+   n++;
+
+   attr = s[8]|(s[9]<<8)|(s[10]<<16)|(s[11]<<24);
+   w = s[12]|(s[13]<<8);
+   h = s[14]|(s[15]<<8);
+
+   s += 16;
+   len -= 16;
+
+   push_text("attr");
+   push_int(attr);
+   n++;
+   push_text("xsize");
+   push_int(w);
+   n++;   
+   push_text("ysize");
+   push_int(h);
+   n++;   
+
+   if(!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:
+      case MODE_TWIDDLE_MIPMAP:
+	twiddle = 1;
+	if(w != h || w<8 || w>1024 || (w&(w-1)))
+	  error("invalid size for twiddle texture\n");
+      case MODE_RECTANGLE:
+      case MODE_STRIDE:
+	break;
+      case MODE_TWIDDLED_RECTANGLE:
+	error("twiddled rectangle not supported\n");
+      case MODE_COMPRESSED:
+      case MODE_COMPRESSED_MIPMAP:
+	error("compressed PVRs not supported\n");
+      case MODE_CLUT4:
+      case MODE_CLUT4_MIPMAP:
+      case MODE_CLUT8:
+      case MODE_CLUT8_MIPMAP:
+	error("palette PVRs not supported\n");
+      default:
+	error("unknown PVR format\n");
+     }
+
+     switch(attr&0xff) {
+      case MODE_ARGB1555:
+      case MODE_ARGB4444:
+	hasalpha=1;
+      case MODE_RGB565:
+      case MODE_RGB555:
+	bpp=2; break;
+      case MODE_YUV422:
+	error("YUV mode not supported\n");
+      case MODE_ARGB8888:
+	error("ARGB8888 mode not supported\n");
+      case MODE_BUMPMAP:
+	error("bumpmap mode not supported\n");
+      default:
+	error("unknown PVR color mode\n");
+     }
+
+     if(len < bpp*(cnt = h*w))
+       error("short PVRT chunk\n");
+
+     push_text("image");
+     push_int(w);
+     push_int(h);
+     o=clone_object(image_program,2);
+     img=(struct image*)get_storage(o,image_program);
+     dst=img->img;
+     push_object(o);
+     n++;
+
+     if(twiddle && !twiddleinited)
+       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;
+       }
+     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;
+       }
+     
+   }
+
+   f_aggregate_mapping(2*n);
+
+#ifdef PVR_DEBUG
+   print_svalue(stderr, sp-1);
+#endif
+
+   stack_swap();
+   pop_stack();
+}
+
+static void image_pvr_f_decode(INT32 args)
+{
+   img_pvr_decode(args,0);
+   push_string(make_shared_string("image"));
+   f_index(2);
+}
+
+static void image_pvr_f_decode_alpha(INT32 args)
+{
+   img_pvr_decode(args,0);
+   push_string(make_shared_string("alpha"));
+   f_index(2);
+}
+
+void image_pvr_f_decode_header(INT32 args)
+{
+   img_pvr_decode(args,1);
+}
+
+void image_pvr_f__decode(INT32 args)
+{
+   img_pvr_decode(args,0);
+}
+
+void init_image_pvr()
+{
+  ADD_FUNCTION( "decode",  image_pvr_f_decode,  tFunc(tStr,tObj), 0);
+  ADD_FUNCTION( "decode_alpha",  image_pvr_f_decode_alpha,  tFunc(tStr,tObj), 0);
+  ADD_FUNCTION( "_decode", image_pvr_f__decode, tFunc(tStr,tMapping), 0);
+  ADD_FUNCTION( "encode",  image_pvr_f_encode,  tFunc(tStr,tObj), 0);
+  ADD_FUNCTION( "decode_header", image_pvr_f_decode_header, tFunc(tStr,tMapping), 0);
+}
+
+void exit_image_pvr()
+{
+}
diff --git a/src/modules/Image/initstuff.h b/src/modules/Image/initstuff.h
index b57ec2234d..52883bb964 100644
--- a/src/modules/Image/initstuff.h
+++ b/src/modules/Image/initstuff.h
@@ -32,6 +32,7 @@ IMAGE_SUBMODULE("ILBM",  init_image_ilbm, exit_image_ilbm )
 IMAGE_SUBMODULE("PCX",   init_image_pcx,  exit_image_pcx  ) 
 IMAGE_SUBMODULE("PNM",   init_image_pnm,  exit_image_pnm  ) 
 IMAGE_SUBMODULE("_PSD",  init_image_psd,  exit_image_psd  ) 
+IMAGE_SUBMODULE("PVR",   init_image_pvr,  exit_image_pvr  )
 IMAGE_SUBMODULE("RAS",   init_image_ras,  exit_image_ras  ) 
 IMAGE_SUBMODULE("TGA",   init_image_tga,  exit_image_tga  ) 
 IMAGE_SUBMODULE("X",     init_image_x,    exit_image_x    ) 
-- 
GitLab