diff options
-rw-r--r-- | Modules/cgen.py | 82 | ||||
-rw-r--r-- | Modules/config.c.in | 7 | ||||
-rw-r--r-- | Modules/cstubs | 64 | ||||
-rw-r--r-- | Modules/rgbimgmodule.c | 712 |
4 files changed, 816 insertions, 49 deletions
diff --git a/Modules/cgen.py b/Modules/cgen.py index ea46263..434765b 100644 --- a/Modules/cgen.py +++ b/Modules/cgen.py @@ -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 diff --git a/Modules/config.c.in b/Modules/config.c.in index b8fc15f..b4f7d3d 100644 --- a/Modules/config.c.in +++ b/Modules/config.c.in @@ -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 */ diff --git a/Modules/cstubs b/Modules/cstubs index 7e99a82..b365f33 100644 --- a/Modules/cstubs +++ b/Modules/cstubs @@ -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 index 0000000..663a460 --- /dev/null +++ b/Modules/rgbimgmodule.c @@ -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"); +} |