]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
rgbimgmodule.c, Makefile, config.c: new module to read RGB image files.
authorSjoerd Mullender <sjoerd@acm.org>
Tue, 21 Dec 1993 17:06:12 +0000 (17:06 +0000)
committerSjoerd Mullender <sjoerd@acm.org>
Tue, 21 Dec 1993 17:06:12 +0000 (17:06 +0000)
Does not need any SGI-specific libraries.
cgen.py, cstubs, Makefile: Generate glmodule.c differently so that it
can be compiled using an ANSI compiler.

Modules/cgen.py
Modules/config.c.in
Modules/cstubs
Modules/rgbimgmodule.c [new file with mode: 0644]

index ea4626365d6265009455206fd7e5991118750261..434765b783f7ce73a0df2941e9cdcf938cbfecd0 100644 (file)
@@ -59,7 +59,7 @@ return_types = ['void', 'short', 'long']
 
 # Allowed function argument types
 #
-arg_types = ['char', 'string', 'short', 'float', 'long', 'double']
+arg_types = ['char', 'string', 'short', 'u_short', 'float', 'long', 'double']
 
 
 # Need to classify arguments as follows
@@ -111,6 +111,8 @@ def checkarg(type, arg):
        #
        if type not in arg_types:
                raise arg_error, ('bad type', type)
+       if type[:2] == 'u_':
+               type = 'unsigned ' + type[2:]
        #
        # Split it in the mode (first character) and the rest.
        #
@@ -157,7 +159,7 @@ def checkarg(type, arg):
                # size is retval -- must be a reply argument
                if mode <> 'r':
                        raise arg_error, ('non-r mode with [retval]', mode)
-       elif sub[:3] <> 'arg' or not isnum(sub[3:]):
+       elif not isnum(sub) and (sub[:3] <> 'arg' or not isnum(sub[3:])):
                raise arg_error, ('bad subscript', sub)
        #
        return type, mode, num, sub
@@ -214,10 +216,16 @@ def generate(type, func, database):
        for i in range(len(database)):
                a_type, a_mode, a_factor, a_sub = database[i]
                print '\t' + a_type,
-               if a_sub:
-                       print '*',
-               print 'arg' + `i+1`,
-               if a_factor and not a_sub:
+               brac = ket = ''
+               if a_sub and not isnum(a_sub):
+                       if a_factor:
+                               brac = '('
+                               ket = ')'
+                       print brac + '*',
+               print 'arg' + `i+1` + ket,
+               if a_sub and isnum(a_sub):
+                       print '[', a_sub, ']',
+               if a_factor:
                        print '[', a_factor, ']',
                print ';'
        #
@@ -250,6 +258,10 @@ def generate(type, func, database):
        #
        for i in range(len(database)):
                a_type, a_mode, a_factor, a_sub = database[i]
+               if a_type[:9] == 'unsigned ':
+                       xtype = a_type[9:]
+               else:
+                       xtype = a_type
                if a_mode == 'i':
                        #
                        # Implicit argument;
@@ -258,9 +270,11 @@ def generate(type, func, database):
                        #
                        j = eval(a_sub)
                        print '\tif',
-                       print '(!geti' + a_type + 'arraysize(args,',
+                       print '(!geti' + xtype + 'arraysize(args,',
                        print `n_in_args` + ',',
                        print `in_pos[j]` + ',',
+                       if xtype <> a_type:
+                               print '('+xtype+' *)',
                        print '&arg' + `i+1` + '))'
                        print '\t\treturn NULL;'
                        if a_factor:
@@ -268,25 +282,34 @@ def generate(type, func, database):
                                print '= arg' + `i+1`,
                                print '/', a_factor + ';'
                elif a_mode == 's':
-                       if a_sub: # Allocate memory for varsize array
+                       if a_sub and not isnum(a_sub):
+                               # Allocate memory for varsize array
                                print '\tif ((arg' + `i+1`, '=',
-                               print 'NEW(' + a_type + ',',
-                               if a_factor: print a_factor, '*',
+                               if a_factor:
+                                       print '('+a_type+'(*)['+a_factor+'])',
+                               print 'NEW(' + a_type, ',',
+                               if a_factor:
+                                       print a_factor, '*',
                                print a_sub, ')) == NULL)'
                                print '\t\treturn err_nomem();'
                        print '\tif',
                        if a_factor or a_sub: # Get a fixed-size array array
-                               print '(!geti' + a_type + 'array(args,',
+                               print '(!geti' + xtype + 'array(args,',
                                print `n_in_args` + ',',
                                print `in_pos[i]` + ',',
                                if a_factor: print a_factor,
                                if a_factor and a_sub: print '*',
                                if a_sub: print a_sub,
-                               print ', arg' + `i+1` + '))'
+                               print ',',
+                               if (a_sub and a_factor) or xtype <> a_type:
+                                       print '('+xtype+' *)',
+                               print 'arg' + `i+1` + '))'
                        else: # Get a simple variable
-                               print '(!geti' + a_type + 'arg(args,',
+                               print '(!geti' + xtype + 'arg(args,',
                                print `n_in_args` + ',',
                                print `in_pos[i]` + ',',
+                               if xtype <> a_type:
+                                       print '('+xtype+' *)',
                                print '&arg' + `i+1` + '))'
                        print '\t\treturn NULL;'
        #
@@ -314,7 +337,7 @@ def generate(type, func, database):
        #
        for i in range(len(database)):
                a_type, a_mode, a_factor, a_sub = database[i]
-               if a_mode == 's' and a_sub:
+               if a_mode == 's' and a_sub and not isnum(a_sub):
                        print '\tDEL(arg' + `i+1` + ');'
        #
        # Return
@@ -373,12 +396,21 @@ def generate(type, func, database):
 # Subroutine to return a function call to mknew<type>object(<arg>)
 #
 def mkobject(type, arg):
+       if type[:9] == 'unsigned ':
+               type = type[9:]
+               return 'mknew' + type + 'object((' + type + ') ' + arg + ')'
        return 'mknew' + type + 'object(' + arg + ')'
 
 
-# Open optional file argument
-if sys.argv[1:]:
-       sys.stdin = open(sys.argv[1], 'r')
+defined_archs = []
+
+# usage: cgen [ -Dmach ... ] [ file ]
+for arg in sys.argv[1:]:
+       if arg[:2] == '-D':
+               defined_archs.append(arg[2:])
+       else:
+               # Open optional file argument
+               sys.stdin = open(arg, 'r')
 
 
 # Input line number
@@ -426,9 +458,19 @@ while 1:
                                        functions.append(func)
                        else:
                                print line
-       elif not words:
-               pass                    # skip empty line
-       elif words[0] == '#include':
+               continue
+       if not words:
+               continue                # skip empty line
+       elif words[0] == 'if':
+               # if XXX rest
+               # if !XXX rest
+               if words[1][0] == '!':
+                       if words[1][1:] in defined_archs:
+                               continue
+               elif words[1] not in defined_archs:
+                       continue
+               words = words[2:]
+       if words[0] == '#include':
                print line
        elif words[0][:1] == '#':
                pass                    # ignore comment
index b8fc15f07c627222d8e5036e4ae4d5a49959ee7e..b4f7d3dfff34fd6e8b66befa78cefc8409316ff7 100644 (file)
@@ -299,6 +299,9 @@ extern void initXlib();
 #ifdef USE_PARSER
 extern void initparser();
 #endif
+#ifdef USE_RGBIMG
+extern void initrgbimg();
+#endif
 /* -- ADDMODULE MARKER 1 -- */
 
 struct {
@@ -482,6 +485,10 @@ struct {
        {"parser", initparser},
 #endif
 
+#ifdef USE_RGBIMG
+       {"rgbimg", initrgbimg},
+#endif
+
 /* -- ADDMODULE MARKER 2 -- */
 
        {0,             0}              /* Sentinel */
index 7e99a82790cad903513a6034c889b2eeade1b07f..b365f33f16ee4404f35d3b96a0f5f826c5c7f4d0 100644 (file)
@@ -22,7 +22,13 @@ Each definition must be contained on one line:
                argI
                retval
                N*argI
+               N*I
                N*retval
+       In the case where the subscript consists of two parts
+       separated by *, the first part is the width of the matrix, and
+       the second part is the length of the matrix.  This order is
+       opposite from the order used in C to declare a two-dimensional
+       matrix.
 */
 
 /*
@@ -847,7 +853,7 @@ gl_gversion(self, args)
 %%
 
 long   getshade
-void   devport         short s long s
+if !solaris    void    devport         short s long s
 void   rdr2i           long s long s
 void   rectfs          short s short s short s short s
 void   rects           short s short s short s short s
@@ -888,7 +894,7 @@ void        textinit
 void   initnames
 void   pclos
 void   popname
-void   spclos
+if !solaris    void    spclos
 void   zclear
 void   screenspace
 void   reshapeviewport
@@ -896,9 +902,9 @@ void        winpush
 void   winpop
 void   foreground
 void   endfullscrn
-void   endpupmode
+if !solaris    void    endpupmode
 void   fullscrn
-void   pupmode
+if !solaris    void    pupmode
 void   winconstraints
 void   pagecolor       short s
 void   textcolor       short s
@@ -910,7 +916,7 @@ void    setlinestyle        short s
 void   setmap          short s
 void   swapinterval    short s
 void   writemask       short s
-void   textwritemask   short s
+if !solaris    void    textwritemask   short s
 void   qdevice         short s
 void   unqdevice       short s
 void   curvebasis      short s
@@ -919,9 +925,9 @@ void        loadname        short s
 void   passthrough     short s
 void   pushname        short s
 void   setmonitor      short s
-void   setshade        short s
+if !solaris    void    setshade        short s
 void   setpattern      short s
-void   pagewritemask   short s
+if !solaris    void    pagewritemask   short s
 #
 void   callobj         long s
 void   delobj          long s
@@ -942,7 +948,7 @@ void        freepup         long s
 #
 void   backbuffer      long s
 void   frontbuffer     long s
-void   lsbackup        long s
+if !solaris    void    lsbackup        long s
 void   resetls         long s
 void   lampon          long s
 void   lampoff         long s
@@ -1003,13 +1009,13 @@ void rpdr2              float s float s
 void rpmv2             float s float s
 void xfpt2             float s float s
 #
-void loadmatrix                float s[16]
+void loadmatrix                float s[4*4]
 # Really [4][4]
-void multmatrix                float s[16]
+void multmatrix                float s[4*4]
 # Really [4][4]
-void crv                       float s[12]
+void crv                       float s[3*4]
 # Really [4][3]
-void rcrv                      float s[16]
+void rcrv                      float s[4*4]
 # Really [4][4]
 #
 # Methods that have strings.  
@@ -1040,12 +1046,12 @@ void polfs              long s short s[3*arg1]
 void polys             long s short s[3*arg1]
 void poly2s            long s short s[2*arg1]
 #
-void defcursor         short s short s[128]
+void defcursor         short s u_short s[128]
 # Is this useful?
-void writepixels       short s short s[arg1]
+void writepixels       short s u_short s[arg1]
 # Should be unsigned short...
-void defbasis          long s float s[16]
-void gewrite           short s short s[arg1]
+void defbasis          long s float s[4*4]
+if !solaris    void gewrite            short s short s[arg1]
 #
 void rotate            short s char s
 # This is not in the library!?
@@ -1103,16 +1109,16 @@ void xfpts              short s short s short s
 void curorigin         short s short s short s
 void cyclemap          short s short s short s
 #
-void patch             float s[16] float s[16] float s[16]
-void splf              long s float s[3*arg1] short s[arg1]
-void splf2             long s float s[2*arg1] short s[arg1]
-void splfi             long s long s[3*arg1] short s[arg1]
-void splf2i            long s long s[2*arg1] short s[arg1]
-void splfs             long s short s[3*arg1] short s[arg1]
-void splf2s            long s short s[2*arg1] short s[arg1]
-###void defpattern             short s short s short s[arg2*arg2/16]
+void patch             float s[4*4] float s[4*4] float s[4*4]
+void splf              long s float s[3*arg1] u_short s[arg1]
+void splf2             long s float s[2*arg1] u_short s[arg1]
+void splfi             long s long s[3*arg1] u_short s[arg1]
+void splf2i            long s long s[2*arg1] u_short s[arg1]
+void splfs             long s short s[3*arg1] u_short s[arg1]
+void splf2s            long s short s[2*arg1] u_short s[arg1]
+###void defpattern             short s short s u_short s[arg2*arg2/16]
 #
-void rpatch            float s[16] float s[16] float s[16] float s[16]
+void rpatch            float s[4*4] float s[4*4] float s[4*4] float s[4*4]
 #
 # routines that send 4 floats
 #
@@ -1154,7 +1160,7 @@ void polarview            float s short s short s short s
 void arcfs             short s short s short s short s short s
 void arcs              short s short s short s short s short s
 void rectcopy          short s short s short s short s short s short s
-void RGBcursor         short s short s short s short s short s short s short s
+if !solaris    void RGBcursor          short s short s short s short s short s short s short s
 #
 long getbutton         short s
 long getcmmode
@@ -1198,7 +1204,7 @@ void getcpos              short r short r
 void getsize           long r long r
 void getorigin         long r long r
 void getviewport       short r short r short r short r
-void gettp             short r short r short r short r
+if !solaris    void gettp              short r short r short r short r
 void getgpos           float r float r float r float r
 void winposition       long s long s long s long s
 void gRGBcolor         short r short r short r
@@ -1210,7 +1216,7 @@ void mapw         long s short s short s float r float r float r float r float r float
 void mapw2             long s short s short s float r float r
 ###void defrasterfont  short s short s short s Fontchar s[arg3] short s short s[4*arg5]
 ###long qread          short r
-void getcursor         short r short r short r long r
+void getcursor         short r u_short r u_short r long r
 #
 #   For these we receive arrays of stuff
 #
@@ -1241,7 +1247,7 @@ void mmode                long s
 void normal            float s[3]
 void overlay           long s
 void RGBrange          short s short s short s short s short s short s short s short s
-void setvideo          long s long s
+if !solaris    void setvideo           long s long s
 void shademodel                long s
 void underlay          long s
 #
diff --git a/Modules/rgbimgmodule.c b/Modules/rgbimgmodule.c
new file mode 100644 (file)
index 0000000..663a460
--- /dev/null
@@ -0,0 +1,712 @@
+/*
+ *     fastimg -
+ *             Faster reading and writing of image files.
+ *
+ *      This code should work on machines with any byte order.
+ *
+ *     Could someone make this run real fast using multiple processors 
+ *     or how about using memory mapped files to speed it up?
+ *
+ *                             Paul Haeberli - 1991
+ *
+ *     Changed to return sizes.
+ *                             Sjoerd Mullender - 1993
+ *     Changed to incorporate into Python.
+ *                             Sjoerd Mullender - 1993
+ */
+#include "allobjects.h"
+#include "modsupport.h"
+#include <unistd.h>
+
+/*
+ *     from image.h
+ *
+ */
+typedef struct {
+    unsigned short     imagic;         /* stuff saved on disk . . */
+    unsigned short     type;
+    unsigned short     dim;
+    unsigned short     xsize;
+    unsigned short     ysize;
+    unsigned short     zsize;
+    unsigned long      min;
+    unsigned long      max;
+    unsigned long      wastebytes;     
+    char               name[80];
+    unsigned long      colormap;
+
+    long               file;           /* stuff used in core only */
+    unsigned short     flags;
+    short              dorev;
+    short              x;
+    short              y;
+    short              z;
+    short              cnt;
+    unsigned short     *ptr;
+    unsigned short     *base;
+    unsigned short     *tmpbuf;
+    unsigned long      offset;
+    unsigned long      rleend;         /* for rle images */
+    unsigned long      *rowstart;      /* for rle images */
+    long               *rowsize;       /* for rle images */
+} IMAGE;
+
+#define IMAGIC         0732
+
+#define TYPEMASK               0xff00
+#define BPPMASK                        0x00ff
+#define ITYPE_VERBATIM         0x0000
+#define ITYPE_RLE              0x0100
+#define ISRLE(type)            (((type) & 0xff00) == ITYPE_RLE)
+#define ISVERBATIM(type)       (((type) & 0xff00) == ITYPE_VERBATIM)
+#define BPP(type)              ((type) & BPPMASK)
+#define RLE(bpp)               (ITYPE_RLE | (bpp))
+#define VERBATIM(bpp)          (ITYPE_VERBATIM | (bpp))
+/*
+ *     end of image.h stuff
+ *
+ */
+
+#define RINTLUM (79)
+#define GINTLUM (156)
+#define BINTLUM (21)
+
+#define ILUM(r,g,b)     ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8)
+
+#define OFFSET_R       3       /* this is byte order dependent */
+#define OFFSET_G       2
+#define OFFSET_B       1
+#define OFFSET_A       0
+
+#define CHANOFFSET(z)  (3-(z)) /* this is byte order dependent */
+
+static expandrow();
+static setalpha();
+static copybw();
+static interleaverow();
+static int compressrow();
+static lumrow();
+
+#ifdef ADD_TAGS
+#define TAGLEN (5)
+#else
+#define TAGLEN (0)
+#endif
+
+static object *ImgfileError;
+
+#ifdef ADD_TAGS
+/*
+ *     addlongimgtag - 
+ *             this is used to extract image data from core dumps.
+ *
+ */
+addlongimgtag(dptr,xsize,ysize)
+unsigned long *dptr;
+int xsize, ysize;
+{
+    dptr = dptr+(xsize*ysize);
+    dptr[0] = 0x12345678;
+    dptr[1] = 0x59493333;
+    dptr[2] = 0x69434222;
+    dptr[3] = xsize;
+    dptr[4] = ysize;
+}
+#endif
+
+/*
+ *     byte order independent read/write of shorts and longs.
+ *
+ */
+static unsigned short getshort(inf)
+FILE *inf;
+{
+    unsigned char buf[2];
+
+    fread(buf,2,1,inf);
+    return (buf[0]<<8)+(buf[1]<<0);
+}
+
+static unsigned long getlong(inf)
+FILE *inf;
+{
+    unsigned char buf[4];
+
+    fread(buf,4,1,inf);
+    return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0);
+}
+
+static putshort(outf,val)
+FILE *outf;
+unsigned short val;
+{
+    unsigned char buf[2];
+
+    buf[0] = (val>>8);
+    buf[1] = (val>>0);
+    fwrite(buf,2,1,outf);
+}
+
+static int putlong(outf,val)
+FILE *outf;
+unsigned long val;
+{
+    unsigned char buf[4];
+
+    buf[0] = (val>>24);
+    buf[1] = (val>>16);
+    buf[2] = (val>>8);
+    buf[3] = (val>>0);
+    return fwrite(buf,4,1,outf);
+}
+
+static readheader(inf,image)
+FILE *inf;
+IMAGE *image;
+{
+    bzero(image,sizeof(IMAGE));
+    image->imagic = getshort(inf);
+    image->type = getshort(inf);
+    image->dim = getshort(inf);
+    image->xsize = getshort(inf);
+    image->ysize = getshort(inf);
+    image->zsize = getshort(inf);
+}
+
+static int writeheader(outf,image)
+FILE *outf;
+IMAGE *image;
+{
+    IMAGE t;
+
+    bzero(&t,sizeof(IMAGE));
+    fwrite(&t,sizeof(IMAGE),1,outf);
+    fseek(outf,0,SEEK_SET);
+    putshort(outf,image->imagic);
+    putshort(outf,image->type);
+    putshort(outf,image->dim);
+    putshort(outf,image->xsize);
+    putshort(outf,image->ysize);
+    putshort(outf,image->zsize);
+    putlong(outf,image->min);
+    putlong(outf,image->max);
+    putlong(outf,0);
+    return fwrite("no name",8,1,outf);
+}
+
+static int writetab(outf,tab,len)
+FILE *outf;
+unsigned long *tab;
+int len;
+{
+    int r;
+
+    while(len) {
+       r = putlong(outf,*tab++);
+       len -= 4;
+    }
+    return r;
+}
+
+static readtab(inf,tab,len)
+FILE *inf;
+unsigned long *tab;
+int len;
+{
+    while(len) {
+       *tab++ = getlong(inf);
+       len -= 4;
+    }
+}
+
+/*
+ *     sizeofimage - 
+ *             return the xsize and ysize of an iris image file.
+ *
+ */
+static object *
+sizeofimage(self, args)
+    object *self, *args;
+{
+    char *name;
+    IMAGE image;
+    FILE *inf;
+
+    if (!getargs(args, "s", &name))
+       return NULL;
+
+    inf = fopen(name,"r");
+    if(!inf) {
+       err_setstr(ImgfileError, "can't open image file");
+       return NULL;
+    }
+    readheader(inf,&image);
+    fclose(inf);
+    if(image.imagic != IMAGIC) {
+       err_setstr(ImgfileError, "bad magic number in image file");
+       return NULL;
+    }
+    return mkvalue("(ii)", image.xsize, image.ysize);
+}
+
+/*
+ *     longimagedata - 
+ *             read in a B/W RGB or RGBA iris image file and return a 
+ *     pointer to an array of longs.
+ *
+ */
+static object *
+longimagedata(self, args)
+    object *self, *args;
+{
+    char *name;
+    unsigned long *base, *lptr;
+    unsigned char *rledat, *verdat;
+    long *starttab, *lengthtab;
+    FILE *inf;
+    IMAGE image;
+    int y, z, pos, len, tablen;
+    int xsize, ysize, zsize;
+    int bpp, rle, cur, badorder;
+    int rlebuflen;
+    object *rv;
+
+    if (!getargs(args, "s", &name))
+       return NULL;
+
+    inf = fopen(name,"r");
+    if(!inf) {
+       err_setstr(ImgfileError,"can't open image file");
+       return NULL;
+    }
+    readheader(inf,&image);
+    if(image.imagic != IMAGIC) {
+       err_setstr(ImgfileError,"bad magic number in image file");
+       fclose(inf);
+       return NULL;
+    }
+    rle = ISRLE(image.type);
+    bpp = BPP(image.type);
+    if(bpp != 1 ) {
+       err_setstr(ImgfileError,"image must have 1 byte per pix chan");
+       fclose(inf);
+       return NULL;
+    }
+    xsize = image.xsize;
+    ysize = image.ysize;
+    zsize = image.zsize;
+    if(rle) {
+       tablen = ysize*zsize*sizeof(long);
+       starttab = (long *)malloc(tablen);
+       lengthtab = (long *)malloc(tablen);
+       rlebuflen = 1.05*xsize+10;
+       rledat = (unsigned char *)malloc(rlebuflen);
+       fseek(inf,512,SEEK_SET);
+       readtab(inf,starttab,tablen);
+       readtab(inf,lengthtab,tablen);
+
+/* check data order */
+       cur = 0;
+       badorder = 0;
+       for(y=0; y<ysize; y++) {
+           for(z=0; z<zsize; z++) {
+               if(starttab[y+z*ysize]<cur) {
+                   badorder = 1;
+                   break;
+               }
+               cur = starttab[y+z*ysize];
+           }
+           if(badorder) 
+               break;
+       }
+
+       fseek(inf,512+2*tablen,SEEK_SET);
+       cur = 512+2*tablen;
+       rv = newsizedstringobject((char *) 0,
+                                 (xsize*ysize+TAGLEN)*sizeof(long));
+       if (rv == NULL) {
+           fclose(inf);
+           free(lengthtab);
+           free(starttab);
+           free(rledat);
+           return NULL;
+       }
+       base = (unsigned long *) getstringvalue(rv);
+#ifdef ADD_TAGS
+       addlongimgtag(base,xsize,ysize);
+#endif
+       if(badorder) {
+           for(z=0; z<zsize; z++) {
+               lptr = base;
+               for(y=0; y<ysize; y++) {
+                   if(cur != starttab[y+z*ysize]) {
+                       fseek(inf,starttab[y+z*ysize],SEEK_SET);
+                       cur = starttab[y+z*ysize];
+                   }
+                   if(lengthtab[y+z*ysize]>rlebuflen) {
+                       err_setstr(ImgfileError,"rlebuf is too small - bad poop");
+                       fclose(inf);
+                       DECREF(rv);
+                       free(rledat);
+                       free(starttab);
+                       free(lengthtab);
+                       return NULL;
+                   }
+                   fread(rledat,lengthtab[y+z*ysize],1,inf);
+                   cur += lengthtab[y+z*ysize];
+                   expandrow(lptr,rledat,3-z);
+                   lptr += xsize;
+               }
+           }
+       } else {
+           lptr = base;
+           for(y=0; y<ysize; y++) {
+               for(z=0; z<zsize; z++) {
+                   if(cur != starttab[y+z*ysize]) {
+                       fseek(inf,starttab[y+z*ysize],SEEK_SET);
+                       cur = starttab[y+z*ysize];
+                   }
+                   fread(rledat,lengthtab[y+z*ysize],1,inf);
+                   cur += lengthtab[y+z*ysize];
+                   expandrow(lptr,rledat,3-z);
+               }
+               lptr += xsize;
+           }
+       }
+       if(zsize == 3) 
+           setalpha(base,xsize*ysize);
+       else if(zsize<3) 
+           copybw(base,xsize*ysize);
+       fclose(inf);
+       free(starttab);
+       free(lengthtab);
+       free(rledat);
+       return rv;
+    } else {
+       rv = newsizedstringobject((char *) 0,
+                                 (xsize*ysize+TAGLEN)*sizeof(long));
+       if (rv == NULL) {
+           fclose(inf);
+           return NULL;
+       }
+       base = (unsigned long *) getstringvalue(rv);
+#ifdef ADD_TAGS
+       addlongimgtag(base,xsize,ysize);
+#endif
+       verdat = (unsigned char *)malloc(xsize);
+       fseek(inf,512,SEEK_SET);
+       for(z=0; z<zsize; z++) {
+           lptr = base;
+           for(y=0; y<ysize; y++) {
+               fread(verdat,xsize,1,inf);
+               interleaverow(lptr,verdat,3-z,xsize);
+               lptr += xsize;
+           }
+       }
+       if(zsize == 3) 
+           setalpha(base,xsize*ysize);
+       else if(zsize<3) 
+           copybw(base,xsize*ysize);
+       fclose(inf);
+       free(verdat);
+       return rv;
+    }
+}
+
+/* static utility functions for longimagedata */
+
+static interleaverow(lptr,cptr,z,n)
+unsigned char *lptr, *cptr;
+int z, n;
+{
+    lptr += z;
+    while(n--) {
+       *lptr = *cptr++;
+       lptr += 4;
+    }
+}
+
+static copybw(lptr,n)
+long *lptr;
+int n;
+{
+    while(n>=8) {
+       lptr[0] = 0xff000000+(0x010101*(lptr[0]&0xff));
+       lptr[1] = 0xff000000+(0x010101*(lptr[1]&0xff));
+       lptr[2] = 0xff000000+(0x010101*(lptr[2]&0xff));
+       lptr[3] = 0xff000000+(0x010101*(lptr[3]&0xff));
+       lptr[4] = 0xff000000+(0x010101*(lptr[4]&0xff));
+       lptr[5] = 0xff000000+(0x010101*(lptr[5]&0xff));
+       lptr[6] = 0xff000000+(0x010101*(lptr[6]&0xff));
+       lptr[7] = 0xff000000+(0x010101*(lptr[7]&0xff));
+       lptr += 8;
+       n-=8;
+    }
+    while(n--) {
+       *lptr = 0xff000000+(0x010101*(*lptr&0xff));
+       lptr++;
+    }
+}
+
+static setalpha(lptr,n)
+unsigned char *lptr;
+{
+    while(n>=8) {
+       lptr[0*4] = 0xff;
+       lptr[1*4] = 0xff;
+       lptr[2*4] = 0xff;
+       lptr[3*4] = 0xff;
+       lptr[4*4] = 0xff;
+       lptr[5*4] = 0xff;
+       lptr[6*4] = 0xff;
+       lptr[7*4] = 0xff;
+       lptr += 4*8;
+       n -= 8;
+    }
+    while(n--) {
+       *lptr = 0xff;
+       lptr += 4;
+    }
+}
+
+static expandrow(optr,iptr,z)
+unsigned char *optr, *iptr;
+int z;
+{
+    unsigned char pixel, count;
+
+    optr += z;
+    while(1) {
+       pixel = *iptr++;
+       if ( !(count = (pixel & 0x7f)) )
+           return;
+       if(pixel & 0x80) {
+           while(count>=8) {
+               optr[0*4] = iptr[0];
+               optr[1*4] = iptr[1];
+               optr[2*4] = iptr[2];
+               optr[3*4] = iptr[3];
+               optr[4*4] = iptr[4];
+               optr[5*4] = iptr[5];
+               optr[6*4] = iptr[6];
+               optr[7*4] = iptr[7];
+               optr += 8*4;
+               iptr += 8;
+               count -= 8;
+           }
+           while(count--) {
+               *optr = *iptr++;
+               optr+=4;
+           }
+       } else {
+           pixel = *iptr++;
+           while(count>=8) {
+               optr[0*4] = pixel;
+               optr[1*4] = pixel;
+               optr[2*4] = pixel;
+               optr[3*4] = pixel;
+               optr[4*4] = pixel;
+               optr[5*4] = pixel;
+               optr[6*4] = pixel;
+               optr[7*4] = pixel;
+               optr += 8*4;
+               count -= 8;
+           }
+           while(count--) {
+               *optr = pixel;
+               optr+=4;
+           }
+       }
+    }
+}
+
+/*
+ *     longstoimage -
+ *             copy an array of longs to an iris image file.  Each long
+ *     represents one pixel.  xsize and ysize specify the dimensions of
+ *     the pixel array.  zsize specifies what kind of image file to
+ *     write out.  if zsize is 1, the luminance of the pixels are
+ *     calculated, and a sinlge channel black and white image is saved.
+ *     If zsize is 3, an RGB image file is saved.  If zsize is 4, an
+ *     RGBA image file is saved.
+ *
+ */
+static object *
+longstoimage(self, args)
+    object *self, *args;
+{
+    unsigned long *lptr;
+    char *name;
+    int xsize, ysize, zsize;
+    FILE *outf;
+    IMAGE image;
+    int tablen, y, z, pos, len;
+    long *starttab, *lengthtab;
+    unsigned char *rlebuf;
+    unsigned long *lumbuf;
+    int rlebuflen, goodwrite;
+
+    if (!getargs(args, "(s#iiis)", &lptr, &len, &xsize, &ysize, &zsize, &name))
+       return NULL;
+
+    goodwrite = 1;
+    outf = fopen(name,"w");
+    if(!outf) {
+       err_setstr(ImgfileError,"can't open output file");
+       return NULL;
+    }
+    tablen = ysize*zsize*sizeof(long);
+
+    starttab = (long *)malloc(tablen);
+    lengthtab = (long *)malloc(tablen);
+    rlebuflen = 1.05*xsize+10;
+    rlebuf = (unsigned char *)malloc(rlebuflen);
+    lumbuf = (unsigned long *)malloc(xsize*sizeof(long));
+
+    bzero(&image,sizeof(IMAGE));
+    image.imagic = IMAGIC; 
+    image.type = RLE(1);
+    if(zsize>1)
+       image.dim = 3;
+    else
+       image.dim = 2;
+    image.xsize = xsize;
+    image.ysize = ysize;
+    image.zsize = zsize;
+    image.min = 0;
+    image.max = 255;
+    goodwrite *= writeheader(outf,&image);
+    fseek(outf,512+2*tablen,SEEK_SET);
+    pos = 512+2*tablen;
+    for(y=0; y<ysize; y++) {
+       for(z=0; z<zsize; z++) {
+           if(zsize == 1) {
+               lumrow(lptr,lumbuf,xsize);
+               len = compressrow(lumbuf,rlebuf,CHANOFFSET(z),xsize);
+           } else {
+               len = compressrow(lptr,rlebuf,CHANOFFSET(z),xsize);
+           }
+           if(len>rlebuflen) {
+               err_setstr(ImgfileError,"rlebuf is too small - bad poop");
+               free(starttab);
+               free(lengthtab);
+               free(rlebuf);
+               free(lumbuf);
+               fclose(outf);
+               return NULL;
+           }
+           goodwrite *= fwrite(rlebuf,len,1,outf);
+           starttab[y+z*ysize] = pos;
+           lengthtab[y+z*ysize] = len;
+           pos += len;
+       }
+       lptr += xsize;
+    }
+
+    fseek(outf,512,SEEK_SET);
+    goodwrite *= writetab(outf,starttab,tablen);
+    goodwrite *= writetab(outf,lengthtab,tablen);
+    free(starttab);
+    free(lengthtab);
+    free(rlebuf);
+    free(lumbuf);
+    fclose(outf);
+    if(goodwrite) {
+       INCREF(None);
+       return None;
+    } else {
+       err_setstr(ImgfileError,"not enough space for image!!");
+       return NULL;
+    }
+}
+
+/* static utility functions for longstoimage */
+
+static lumrow(rgbptr,lumptr,n) 
+unsigned char *rgbptr, *lumptr;
+int n;
+{
+    lumptr += CHANOFFSET(0);
+    while(n--) {
+       *lumptr = ILUM(rgbptr[OFFSET_R],rgbptr[OFFSET_G],rgbptr[OFFSET_B]);
+       lumptr += 4;
+       rgbptr += 4;
+    }
+}
+
+static int compressrow(lbuf,rlebuf,z,cnt)
+unsigned char *lbuf, *rlebuf;
+int z, cnt;
+{
+    unsigned char *iptr, *ibufend, *sptr, *optr;
+    short todo, cc;                                                    
+    long count;
+
+    lbuf += z;
+    iptr = lbuf;
+    ibufend = iptr+cnt*4;
+    optr = rlebuf;
+
+    while(iptr<ibufend) {
+       sptr = iptr;
+       iptr += 8;
+       while((iptr<ibufend)&& ((iptr[-8]!=iptr[-4])||(iptr[-4]!=iptr[0])))
+           iptr+=4;
+       iptr -= 8;
+       count = (iptr-sptr)/4;
+       while(count) {
+           todo = count>126 ? 126:count;
+           count -= todo;
+           *optr++ = 0x80|todo;
+           while(todo>8) {
+               optr[0] = sptr[0*4];
+               optr[1] = sptr[1*4];
+               optr[2] = sptr[2*4];
+               optr[3] = sptr[3*4];
+               optr[4] = sptr[4*4];
+               optr[5] = sptr[5*4];
+               optr[6] = sptr[6*4];
+               optr[7] = sptr[7*4];
+               optr += 8;
+               sptr += 8*4;
+               todo -= 8;
+           }
+           while(todo--) {
+               *optr++ = *sptr;
+               sptr += 4;
+           }
+       }
+       sptr = iptr;
+       cc = *iptr;
+       iptr += 4;
+       while( (iptr<ibufend) && (*iptr == cc) )
+           iptr += 4;
+       count = (iptr-sptr)/4;
+       while(count) {
+           todo = count>126 ? 126:count;
+           count -= todo;
+           *optr++ = todo;
+           *optr++ = cc;
+       }
+    }
+    *optr++ = 0;
+    return optr - (unsigned char *)rlebuf;
+}
+
+static struct methodlist rgbimg_methods[] = {
+    {"sizeofimage",    sizeofimage},
+    {"longimagedata",  longimagedata},
+    {"longstoimage",   longstoimage},
+    {NULL, NULL}               /* sentinel */
+};
+
+void
+initrgbimg()
+{
+    object *m, *d;
+    m = initmodule("rgbimg", rgbimg_methods);
+    d = getmoduledict(m);
+    ImgfileError = newstringobject("rgbimg,error");
+    if (ImgfileError == NULL || dictinsert(d, "error", ImgfileError))
+       fatal("can't define rgbimg.error");
+}