/* IMGFILE module - Interface to sgi libimage *//* XXX This module should be done better at some point. It should return** an object of image file class, and have routines to manipulate these** image files in a neater way (so you can get rgb images off a greyscale** file, for instance, or do a straight display without having to get the** image bits into python, etc).**** Warning: this module is very non-reentrant (esp. the readscaled stuff)*/#include "Python.h"#include <gl/image.h>#include "/usr/people/4Dgifts/iristools/include/izoom.h"/* Bunch of missing extern decls; keep gcc -Wall happy... */externvoidi_seterror();externvoidiclose();externvoidfilterzoom();externvoidputrow();externvoidgetrow();staticPyObject*ImgfileError;/* Exception we raise for various trouble */staticinttop_to_bottom;/* True if we want top-to-bottom images *//* The image library does not always call the error hander :-(, therefore we have a global variable indicating that it was called. It is cleared by imgfile_open(). */staticinterror_called;/* The error handler */staticvoidimgfile_error(char*str){PyErr_SetString(ImgfileError,str);error_called=1;return;/* To imglib, which will return a failure indicator */}/* Open an image file and return a pointer to it. Make sure we raise an exception if we fail. */staticIMAGE*imgfile_open(char*fname){IMAGE*image;i_seterror(imgfile_error);error_called=0;errno=0;if((image=iopen(fname,"r"))==NULL){/* Error may already be set by imgfile_error */if(!error_called){if(errno)PyErr_SetFromErrno(ImgfileError);elsePyErr_SetString(ImgfileError,"Can't open image file");}returnNULL;}returnimage;}staticPyObject*imgfile_ttob(PyObject*self,PyObject*args){intnewval;PyObject*rv;if(!PyArg_Parse(args,"i",&newval))returnNULL;rv=PyInt_FromLong(top_to_bottom);top_to_bottom=newval;returnrv;}staticPyObject*imgfile_read(PyObject*self,PyObject*args){char*fname;PyObject*rv;intxsize,ysize,zsize;char*cdatap;long*idatap;staticshortrs[8192],gs[8192],bs[8192];intx,y;IMAGE*image;intyfirst,ylast,ystep;if(!PyArg_Parse(args,"s",&fname))returnNULL;if((image=imgfile_open(fname))==NULL)returnNULL;if(image->colormap!=CM_NORMAL){iclose(image);PyErr_SetString(ImgfileError,"Can only handle CM_NORMAL images");returnNULL;}if(BPP(image->type)!=1){iclose(image);PyErr_SetString(ImgfileError,"Can't handle imgfiles with bpp!=1");returnNULL;}xsize=image->xsize;ysize=image->ysize;zsize=image->zsize;if(zsize!=1&&zsize!=3){iclose(image);PyErr_SetString(ImgfileError,"Can only handle 1 or 3 byte pixels");returnNULL;}if(xsize>8192){iclose(image);PyErr_SetString(ImgfileError,"Can't handle image with > 8192 columns");returnNULL;}if(zsize==3)zsize=4;rv=PyString_FromStringAndSize((char*)NULL,xsize*ysize*zsize);if(rv==NULL){iclose(image);returnNULL;}cdatap=PyString_AsString(rv);idatap=(long*)cdatap;if(top_to_bottom){yfirst=ysize-1;ylast=-1;ystep=-1;}else{yfirst=0;ylast=ysize;ystep=1;}for(y=yfirst;y!=ylast&&!error_called;y+=ystep){if(zsize==1){getrow(image,rs,y,0);for(x=0;x<xsize;x++)*cdatap++=rs[x];}else{getrow(image,rs,y,0);getrow(image,gs,y,1);getrow(image,bs,y,2);for(x=0;x<xsize;x++)*idatap++=(rs[x]&0xff)|((gs[x]&0xff)<<8)|((bs[x]&0xff)<<16);}}iclose(image);if(error_called){Py_DECREF(rv);returnNULL;}returnrv;}staticIMAGE*glob_image;staticlong*glob_datap;staticintglob_width,glob_z,glob_ysize;staticvoidxs_get(short*buf,inty){if(top_to_bottom)getrow(glob_image,buf,(glob_ysize-1-y),glob_z);elsegetrow(glob_image,buf,y,glob_z);}staticvoidxs_put_c(short*buf,inty){char*datap=(char*)glob_datap+y*glob_width;intwidth=glob_width;while(width--)*datap++=(*buf++)&0xff;}staticvoidxs_put_0(short*buf,inty){long*datap=glob_datap+y*glob_width;intwidth=glob_width;while(width--)*datap++=(*buf++)&0xff;}staticvoidxs_put_12(short*buf,inty){long*datap=glob_datap+y*glob_width;intwidth=glob_width;while(width--)*datap++|=((*buf++)&0xff)<<(glob_z*8);}staticvoidxscale(IMAGE*image,intxsize,intysize,intzsize,long*datap,intxnew,intynew,intfmode,doubleblur){glob_image=image;glob_datap=datap;glob_width=xnew;glob_ysize=ysize;if(zsize==1){glob_z=0;filterzoom(xs_get,xs_put_c,xsize,ysize,xnew,ynew,fmode,blur);}else{glob_z=0;filterzoom(xs_get,xs_put_0,xsize,ysize,xnew,ynew,fmode,blur);glob_z=1;filterzoom(xs_get,xs_put_12,xsize,ysize,xnew,ynew,fmode,blur);glob_z=2;filterzoom(xs_get,xs_put_12,xsize,ysize,xnew,ynew,fmode,blur);}}staticPyObject*imgfile_readscaled(PyObject*self,PyObject*args){char*fname;PyObject*rv;intxsize,ysize,zsize;char*cdatap;long*idatap;staticshortrs[8192],gs[8192],bs[8192];intx,y;intxwtd,ywtd,xorig,yorig;floatxfac,yfac;intcnt;IMAGE*image;char*filter;doubleblur;intextended;intfmode=0;intyfirst,ylast,ystep;/* ** Parse args. Funny, since arg 4 and 5 are optional ** (filter name and blur factor). Also, 4 or 5 arguments indicates ** extended scale algorithm in stead of simple-minded pixel drop/dup. */extended=0;cnt=PyTuple_Size(args);if(cnt==5){extended=1;if(!PyArg_Parse(args,"(siisd)",&fname,&xwtd,&ywtd,&filter,&blur))returnNULL;}elseif(cnt==4){extended=1;if(!PyArg_Parse(args,"(siis)",&fname,&xwtd,&ywtd,&filter))returnNULL;blur=1.0;}elseif(!PyArg_Parse(args,"(sii)",&fname,&xwtd,&ywtd))returnNULL;/* ** Check parameters, open file and check type, rows, etc. */if(extended){if(strcmp(filter,"impulse")==0)fmode=IMPULSE;elseif(strcmp(filter,"box")==0)fmode=BOX;elseif(strcmp(filter,"triangle")==0)fmode=TRIANGLE;elseif(strcmp(filter,"quadratic")==0)fmode=QUADRATIC;elseif(strcmp(filter,"gaussian")==0)fmode=GAUSSIAN;else{PyErr_SetString(ImgfileError,"Unknown filter type");returnNULL;}}if((image=imgfile_open(fname))==NULL)returnNULL;if(image->colormap!=CM_NORMAL){iclose(image);PyErr_SetString(ImgfileError,"Can only handle CM_NORMAL images");returnNULL;}if(BPP(image->type)!=1){iclose(image);PyErr_SetString(ImgfileError,"Can't handle imgfiles with bpp!=1");returnNULL;}xsize=image->xsize;ysize=image->ysize;zsize=image->zsize;if(zsize!=1&&zsize!=3){iclose(image);PyErr_SetString(ImgfileError,"Can only handle 1 or 3 byte pixels");returnNULL;}if(xsize>8192){iclose(image);PyErr_SetString(ImgfileError,"Can't handle image with > 8192 columns");returnNULL;}if(zsize==3)zsize=4;rv=PyString_FromStringAndSize(NULL,xwtd*ywtd*zsize);if(rv==NULL){iclose(image);returnNULL;}PyFPE_START_PROTECT("readscaled",return0)xfac=(float)xsize/(float)xwtd;yfac=(float)ysize/(float)ywtd;PyFPE_END_PROTECT(yfac)cdatap=PyString_AsString(rv);idatap=(long*)cdatap;if(extended){xscale(image,xsize,ysize,zsize,idatap,xwtd,ywtd,fmode,blur);}else{if(top_to_bottom){yfirst=ywtd-1;ylast=-1;ystep=-1;}else{yfirst=0;ylast=ywtd;ystep=1;}for(y=yfirst;y!=ylast&&!error_called;y+=ystep){yorig=(int)(y*yfac);if(zsize==1){getrow(image,rs,yorig,0);for(x=0;x<xwtd;x++){*cdatap++=rs[(int)(x*xfac)];}}else{getrow(image,rs,yorig,0);getrow(image,gs,yorig,1);getrow(image,bs,yorig,2);for(x=0;x<xwtd;x++){xorig=(int)(x*xfac);*idatap++=(rs[xorig]&0xff)|((gs[xorig]&0xff)<<8)|((bs[xorig]&0xff)<<16);}}}}iclose(image);if(error_called){Py_DECREF(rv);returnNULL;}returnrv;}staticPyObject*imgfile_getsizes(PyObject*self,PyObject*args){char*fname;PyObject*rv;IMAGE*image;if(!PyArg_Parse(args,"s",&fname))returnNULL;if((image=imgfile_open(fname))==NULL)returnNULL;rv=Py_BuildValue("(iii)",image->xsize,image->ysize,image->zsize);iclose(image);returnrv;}staticPyObject*imgfile_write(PyObject*self,PyObject*args){IMAGE*image;char*fname;intxsize,ysize,zsize,len;char*cdatap;long*idatap;shortrs[8192],gs[8192],bs[8192];shortr,g,b;longrgb;intx,y;intyfirst,ylast,ystep;if(!PyArg_Parse(args,"(ss#iii)",&fname,&cdatap,&len,&xsize,&ysize,&zsize))returnNULL;if(zsize!=1&&zsize!=3){PyErr_SetString(ImgfileError,"Can only handle 1 or 3 byte pixels");returnNULL;}if(len!=xsize*ysize*(zsize==1?1:4)){PyErr_SetString(ImgfileError,"Data does not match sizes");returnNULL;}if(xsize>8192){PyErr_SetString(ImgfileError,"Can't handle image with > 8192 columns");returnNULL;}error_called=0;errno=0;image=iopen(fname,"w",RLE(1),3,xsize,ysize,zsize);if(image==0){if(!error_called){if(errno)PyErr_SetFromErrno(ImgfileError);elsePyErr_SetString(ImgfileError,"Can't create image file");}returnNULL;}idatap=(long*)cdatap;if(top_to_bottom){yfirst=ysize-1;ylast=-1;ystep=-1;}else{yfirst=0;ylast=ysize;ystep=1;}for(y=yfirst;y!=ylast&&!error_called;y+=ystep){if(zsize==1){for(x=0;x<xsize;x++)rs[x]=*cdatap++;putrow(image,rs,y,0);}else{for(x=0;x<xsize;x++){rgb=*idatap++;r=rgb&0xff;g=(rgb>>8)&0xff;b=(rgb>>16)&0xff;rs[x]=r;gs[x]=g;bs[x]=b;}putrow(image,rs,y,0);putrow(image,gs,y,1);putrow(image,bs,y,2);}}iclose(image);if(error_called)returnNULL;Py_INCREF(Py_None);returnPy_None;}staticPyMethodDefimgfile_methods[]={{"getsizes",imgfile_getsizes},{"read",imgfile_read},{"readscaled",imgfile_readscaled,1},{"write",imgfile_write},{"ttob",imgfile_ttob},{NULL,NULL}/* Sentinel */};voidinitimgfile(void){PyObject*m,*d;m=Py_InitModule("imgfile",imgfile_methods);d=PyModule_GetDict(m);ImgfileError=PyErr_NewException("imgfile.error",NULL,NULL);if(ImgfileError!=NULL)PyDict_SetItemString(d,"error",ImgfileError);}