Staging
v0.5.1
https://github.com/python/cpython
Revision 5baf4bc97863dc2a5e89ca22ac73bdbf34dff925 authored by Guido van Rossum on 29 December 1997, 20:05:45 UTC, committed by Guido van Rossum on 29 December 1997, 20:05:45 UTC
input.  When an EOF is read, break out of the loop instead of (by
default) writing an empty line (which doesn't do much good).  Don't
close self when falling through the loop.
1 parent 588f38e
Raw File
Tip revision: 5baf4bc97863dc2a5e89ca22ac73bdbf34dff925 authored by Guido van Rossum on 29 December 1997, 20:05:45 UTC
Moved things around a bit in interact(), so outout is processed before
Tip revision: 5baf4bc
rgbimgmodule.c
/*
 *   	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"

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#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;
	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 void expandrow Py_PROTO((unsigned char *, unsigned char *, int));
static void setalpha Py_PROTO((unsigned char *, int));
static void copybw Py_PROTO((long *, int));
static void interleaverow Py_PROTO((unsigned char*, unsigned char*, int, int));
static int compressrow Py_PROTO((unsigned char *, unsigned char *, int, int));
static void lumrow Py_PROTO((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(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 void
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] = (unsigned char) (val >> 24);
	buf[1] = (unsigned char) (val >> 16);
	buf[2] = (unsigned char) (val >> 8);
	buf[3] = (unsigned char) (val >> 0);
	return fwrite(buf, 4, 1, outf);
}

static void
readheader(inf, image)
	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 int
writeheader(outf, image)
	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 fwrite("no name", 8, 1, outf);
}

static int
writetab(outf, tab, len)
	FILE *outf;
	/*unsigned*/ long *tab;
	int len;
{
	int r = 0;

	while(len) {
		r = putlong(outf, *tab++);
		len--;
	}
	return r;
}

static void
readtab(inf, tab, len)
	FILE *inf;
	/*unsigned*/ long *tab;
	int len;
{
	while(len) {
		*tab++ = getlong(inf);
		len--;
	}
}

/*
 *	sizeofimage - 
 *		return the xsize and ysize of an iris image file.
 *
 */
static PyObject *
sizeofimage(self, args)
	PyObject *self, *args;
{
	char *name;
	IMAGE image;
	FILE *inf;

	if (!PyArg_Parse(args, "s", &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(self, args)
	PyObject *self, *args;
{
	char *name;
	unsigned char *base, *lptr;
	unsigned char *rledat = NULL, *verdat = NULL;
	long *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_Parse(args, "s", &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(long);
		starttab = (long *)malloc(tablen);
		lengthtab = (long *)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(long));
		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(unsigned long);
				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(unsigned long);
					else
						lptr += xsize
						      * sizeof(unsigned long);
				}
			}
		} else {
			lptr = base;
			if (reverse_order)
				lptr += (ysize - 1) * xsize
					* sizeof(unsigned long);
			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(unsigned long);
				else
					lptr += xsize * sizeof(unsigned long);
			}
		}
		if (zsize == 3) 
			setalpha(base, xsize * ysize);
		else if (zsize < 3) 
			copybw((long *) base, xsize * ysize);
	}
	else {
		rv = PyString_FromStringAndSize((char *) 0,
					   (xsize*ysize+TAGLEN)*sizeof(long));
		if (rv == NULL)
			goto finally;

		base = (unsigned char *) PyString_AsString(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;
			if (reverse_order)
				lptr += (ysize - 1) * xsize
				        * sizeof(unsigned long);
			for (y = 0; y < ysize; y++) {
				fread(verdat, xsize, 1, inf);
				interleaverow(lptr, verdat, 3-z, xsize);
				if (reverse_order)
					lptr -= xsize * sizeof(unsigned long);
				else
					lptr += xsize * sizeof(unsigned long);
			}
		}
		if (zsize == 3)
			setalpha(base, xsize * ysize);
		else if (zsize < 3) 
			copybw((long *) base, xsize * ysize);
	}
  finally:
	free(starttab);
	free(lengthtab);
	free(rledat);
	free(verdat);
	fclose(inf);
	return rv;
}

/* static utility functions for longimagedata */

static void
interleaverow(lptr, cptr, z, n)
	unsigned char *lptr, *cptr;
	int z, n;
{
	lptr += z;
	while (n--) {
		*lptr = *cptr++;
		lptr += 4;
	}
}

static void
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 void
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 void
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 PyObject *
longstoimage(self, args)
	PyObject *self, *args;
{
	unsigned char *lptr;
	char *name;
	int xsize, ysize, zsize;
	FILE *outf = NULL;
	IMAGE image;
	int tablen, y, z, pos, len;
	long *starttab = NULL, *lengthtab = NULL;
	unsigned char *rlebuf = NULL;
	unsigned char *lumbuf = NULL;
	int rlebuflen, goodwrite;
	PyObject *retval = NULL;

	if (!PyArg_Parse(args, "(s#iiis)", &lptr, &len, &xsize, &ysize, &zsize,
			 &name))
		return NULL;

	goodwrite = 1;
	outf = fopen(name, "wb");
	if (!outf) {
		PyErr_SetString(ImgfileError, "can't open output file");
		return NULL;
	}
	tablen = ysize * zsize * sizeof(long);

	starttab = (long *)malloc(tablen);
	lengthtab = (long *)malloc(tablen);
	rlebuflen = (int) (1.05 * xsize + 10);
	rlebuf = (unsigned char *)malloc(rlebuflen);
	lumbuf = (unsigned char *)malloc(xsize * sizeof(long));
	if (!starttab || !lengthtab || !rlebuf || !lumbuf) {
		PyErr_NoMemory();
		goto finally;
	}
	
	memset(&image, 0, 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);
	pos = 512 + 2 * tablen;
	fseek(outf, pos, SEEK_SET);
	if (reverse_order)
		lptr += (ysize - 1) * xsize * sizeof(unsigned long);
	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) {
				PyErr_SetString(ImgfileError,
						"rlebuf is too small");
				goto finally;
			}
			goodwrite *= fwrite(rlebuf, len, 1, outf);
			starttab[y + z * ysize] = pos;
			lengthtab[y + z * ysize] = len;
			pos += len;
		}
		if (reverse_order)
			lptr -= xsize * sizeof(unsigned long);
		else
			lptr += xsize * sizeof(unsigned long);
	}

	fseek(outf, 512, SEEK_SET);
	goodwrite *= writetab(outf, starttab, ysize*zsize);
	goodwrite *= writetab(outf, lengthtab, ysize*zsize);
	if (goodwrite) {
		Py_INCREF(Py_None);
		retval = Py_None;
	} else
		PyErr_SetString(ImgfileError, "not enough space for image");

  finally:
	fclose(outf);
	free(starttab);
	free(lengthtab);
	free(rlebuf);
	free(lumbuf);
	return retval;
}

/* static utility functions for longstoimage */

static void
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 : (short)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 : (short)count;
			count -= todo;
			*optr++ = (unsigned char) todo;
			*optr++ = (unsigned char) cc;
		}
	}
	*optr++ = 0;
	return optr - (unsigned char *)rlebuf;
}

static PyObject *
ttob(self, args)
	PyObject *self;
	PyObject *args;
{
	int order, oldorder;

	if (!PyArg_Parse(args, "i", &order))
		return NULL;
	oldorder = reverse_order;
	reverse_order = order;
	return PyInt_FromLong(oldorder);
}

static PyMethodDef
rgbimg_methods[] = {
	{"sizeofimage",	   sizeofimage},
	{"longimagedata",  longimagedata},
	{"longstoimage",   longstoimage},
	{"ttob",	   ttob},
	{NULL,             NULL}	     /* sentinel */
};


void
initrgbimg()
{
	PyObject *m, *d;
	m = Py_InitModule("rgbimg", rgbimg_methods);
	d = PyModule_GetDict(m);
	ImgfileError = PyErr_NewException("rgbimg.error", NULL, NULL);
	if (ImgfileError != NULL)
		PyDict_SetItemString(d, "error", ImgfileError);
}
back to top