780 lines · 16.7 KB · C
RawDownload
/* *   	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 "Python.h" #if SIZEOF_INT == 4typedef int Py_Int32;typedef unsigned int Py_UInt32;#else#if SIZEOF_LONG == 4typedef long Py_Int32;typedef unsigned long Py_UInt32;#else#error "No 4-byte integral type"#endif#endif #include <string.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;	Py_UInt32 	min;	Py_UInt32 	max;	Py_UInt32	wastebytes;		char 		name[80];	Py_UInt32	colormap; 	Py_Int32	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;	Py_UInt32	offset;	Py_UInt32	rleend;		/* for rle images */	Py_UInt32	*rowstart;	/* for rle images */	Py_Int32	*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 void expandrow(unsigned char *, unsigned char *, int);static void setalpha(unsigned char *, int);static void copybw(Py_Int32 *, int);static void interleaverow(unsigned char*, unsigned char*, int, int);static int compressrow(unsigned char *, unsigned char *, int, int);static void lumrow(unsigned char *, unsigned char *, int); #ifdef ADD_TAGS#define TAGLEN	(5)#else#define TAGLEN	(0)#endif static PyObject *ImgfileError; static int reverse_order; #ifdef ADD_TAGS/* *	addlongimgtag -  *		this is used to extract image data from core dumps. * */static void addlongimgtag(Py_UInt32 *dptr, int xsize, int 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 shortgetshort(FILE *inf){	unsigned char buf[2]; 	fread(buf, 2, 1, inf);	return (buf[0] << 8) + (buf[1] << 0);} static Py_UInt32getlong(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 voidputshort(FILE *outf, unsigned short val){	unsigned char buf[2]; 	buf[0] = (val >> 8);	buf[1] = (val >> 0);	fwrite(buf, 2, 1, outf);} static intputlong(FILE *outf, Py_UInt32 val){	unsigned char buf[4]; 	buf[0] = (unsigned char) (val >> 24);	buf[1] = (unsigned char) (val >> 16);	buf[2] = (unsigned char) (val >> 8);	buf[3] = (unsigned char) (val >> 0);	return (int)fwrite(buf, 4, 1, outf);} static voidreadheader(FILE *inf, IMAGE *image){	memset(image ,0, 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 intwriteheader(FILE *outf, IMAGE *image){	IMAGE t; 	memset(&t, 0, 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 (int)fwrite("no name", 8, 1, outf);} static intwritetab(FILE *outf, /*unsigned*/ Py_Int32 *tab, int len){	int r = 0; 	while(len) {		r = putlong(outf, *tab++);		len--;	}	return r;} static voidreadtab(FILE *inf, /*unsigned*/ Py_Int32 *tab, int len){	while(len) {		*tab++ = getlong(inf);		len--;	}} /* *	sizeofimage -  *		return the xsize and ysize of an iris image file. * */static PyObject *sizeofimage(PyObject *self, PyObject *args){	char *name;	IMAGE image;	FILE *inf; 	if (!PyArg_ParseTuple(args, "s:sizeofimage", &name))		return NULL; 	inf = fopen(name, "rb");	if (!inf) {		PyErr_SetString(ImgfileError, "can't open image file");		return NULL;	}	readheader(inf, &image);	fclose(inf);	if (image.imagic != IMAGIC) {		PyErr_SetString(ImgfileError,				"bad magic number in image file");		return NULL;	}	return Py_BuildValue("(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 PyObject *longimagedata(PyObject *self, PyObject *args){	char *name;	unsigned char *base, *lptr;	unsigned char *rledat = NULL, *verdat = NULL;	Py_Int32 *starttab = NULL, *lengthtab = NULL;	FILE *inf = NULL;	IMAGE image;	int y, z, tablen;	int xsize, ysize, zsize;	int bpp, rle, cur, badorder;	int rlebuflen;	PyObject *rv = NULL; 	if (!PyArg_ParseTuple(args, "s:longimagedata", &name))		return NULL; 	inf = fopen(name,"rb");	if (!inf) {		PyErr_SetString(ImgfileError, "can't open image file");		return NULL;	}	readheader(inf,&image);	if (image.imagic != IMAGIC) {		PyErr_SetString(ImgfileError,				"bad magic number in image file");		goto finally;	}	rle = ISRLE(image.type);	bpp = BPP(image.type);	if (bpp != 1) {		PyErr_SetString(ImgfileError,				"image must have 1 byte per pix chan");		goto finally;	}	xsize = image.xsize;	ysize = image.ysize;	zsize = image.zsize;	if (rle) {		tablen = ysize * zsize * sizeof(Py_Int32);		starttab = (Py_Int32 *)malloc(tablen);		lengthtab = (Py_Int32 *)malloc(tablen);		rlebuflen = (int) (1.05 * xsize +10);		rledat = (unsigned char *)malloc(rlebuflen);		if (!starttab || !lengthtab || !rledat) {			PyErr_NoMemory();			goto finally;		}				fseek(inf, 512, SEEK_SET);		readtab(inf, starttab, ysize*zsize);		readtab(inf, lengthtab, ysize*zsize); 		/* 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 = PyString_FromStringAndSize((char *)NULL,				      (xsize * ysize + TAGLEN) * sizeof(Py_Int32));		if (rv == NULL)			goto finally; 		base = (unsigned char *) PyString_AsString(rv);#ifdef ADD_TAGS		addlongimgtag(base,xsize,ysize);#endif		if (badorder) {			for (z = 0; z < zsize; z++) {				lptr = base;				if (reverse_order)					lptr += (ysize - 1) * xsize						* sizeof(Py_UInt32);				for (y = 0; y < ysize; y++) {					int idx = y + z * ysize;					if (cur != starttab[idx]) {						fseek(inf,starttab[idx],						      SEEK_SET);						cur = starttab[idx];					}					if (lengthtab[idx] > rlebuflen) {						PyErr_SetString(ImgfileError,							"rlebuf is too small");						Py_DECREF(rv);						rv = NULL;						goto finally;					}					fread(rledat, lengthtab[idx], 1, inf);					cur += lengthtab[idx];					expandrow(lptr, rledat, 3-z);					if (reverse_order)						lptr -= xsize						      * sizeof(Py_UInt32);					else						lptr += xsize						      * sizeof(Py_UInt32);				}			}		} else {			lptr = base;			if (reverse_order)				lptr += (ysize - 1) * xsize					* sizeof(Py_UInt32);			for (y = 0; y < ysize; y++) {				for(z = 0; z < zsize; z++) {					int idx = y + z * ysize;					if (cur != starttab[idx]) {						fseek(inf, starttab[idx],						      SEEK_SET);						cur = starttab[idx];					}					fread(rledat, lengthtab[idx], 1, inf);					cur += lengthtab[idx];					expandrow(lptr, rledat, 3-z);				}				if (reverse_order)					lptr -= xsize * sizeof(Py_UInt32);				else					lptr += xsize * sizeof(Py_UInt32);			}		}		if (zsize == 3) 			setalpha(base, xsize * ysize);		else if (zsize < 3) 			copybw((Py_Int32 *) base, xsize * ysize);	}	else {		rv = PyString_FromStringAndSize((char *) 0,					   (xsize*ysize+TAGLEN)*sizeof(Py_Int32));		if (rv == NULL)			goto finally; 		base = (unsigned char *) PyString_AsString(rv);#ifdef ADD_TAGS		addlongimgtag(base, xsize, ysize);#endif		verdat = (unsigned char *)malloc(xsize);		if (!verdat) {			Py_CLEAR(rv);			goto finally;		} 		fseek(inf, 512, SEEK_SET);		for (z = 0; z < zsize; z++) {			lptr = base;			if (reverse_order)				lptr += (ysize - 1) * xsize				        * sizeof(Py_UInt32);			for (y = 0; y < ysize; y++) {				fread(verdat, xsize, 1, inf);				interleaverow(lptr, verdat, 3-z, xsize);				if (reverse_order)					lptr -= xsize * sizeof(Py_UInt32);				else					lptr += xsize * sizeof(Py_UInt32);			}		}		if (zsize == 3)			setalpha(base, xsize * ysize);		else if (zsize < 3) 			copybw((Py_Int32 *) base, xsize * ysize);	}  finally:	if (starttab)		free(starttab);	if (lengthtab)		free(lengthtab);	if (rledat)		free(rledat);	if (verdat)		free(verdat);	fclose(inf);	return rv;} /* static utility functions for longimagedata */ static voidinterleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n){	lptr += z;	while (n--) {		*lptr = *cptr++;		lptr += 4;	}} static voidcopybw(Py_Int32 *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 voidsetalpha(unsigned char *lptr, int n){	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;

Lines 1–500 of 780.