diff options
author | cinap_lenrek <cinap_lenrek@localhost> | 2011-05-03 11:25:13 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@localhost> | 2011-05-03 11:25:13 +0000 |
commit | 458120dd40db6b4df55a4e96b650e16798ef06a0 (patch) | |
tree | 8f82685be24fef97e715c6f5ca4c68d34d5074ee /sys/src/cmd/python/Modules/rgbimgmodule.c | |
parent | 3a742c699f6806c1145aea5149bf15de15a0afd7 (diff) |
add hg and python
Diffstat (limited to 'sys/src/cmd/python/Modules/rgbimgmodule.c')
-rw-r--r-- | sys/src/cmd/python/Modules/rgbimgmodule.c | 780 |
1 files changed, 780 insertions, 0 deletions
diff --git a/sys/src/cmd/python/Modules/rgbimgmodule.c b/sys/src/cmd/python/Modules/rgbimgmodule.c new file mode 100644 index 000000000..0f9ee71f2 --- /dev/null +++ b/sys/src/cmd/python/Modules/rgbimgmodule.c @@ -0,0 +1,780 @@ +/* + * 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 == 4 +typedef int Py_Int32; +typedef unsigned int Py_UInt32; +#else +#if SIZEOF_LONG == 4 +typedef 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 short +getshort(FILE *inf) +{ + unsigned char buf[2]; + + fread(buf, 2, 1, inf); + return (buf[0] << 8) + (buf[1] << 0); +} + +static Py_UInt32 +getlong(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(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(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 void +readheader(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(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 int +writetab(FILE *outf, /*unsigned*/ Py_Int32 *tab, int len) +{ + int r = 0; + + while(len) { + r = putlong(outf, *tab++); + len--; + } + return r; +} + +static void +readtab(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 void +interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n) +{ + lptr += z; + while (n--) { + *lptr = *cptr++; + lptr += 4; + } +} + +static void +copybw(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 void +setalpha(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; + lptr += 4; + } +} + +static void +expandrow(unsigned char *optr, unsigned char *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 single 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(PyObject *self, PyObject *args) +{ + unsigned char *lptr; + char *name; + int xsize, ysize, zsize; + FILE *outf = NULL; + IMAGE image; + int tablen, y, z, pos, len; + Py_Int32 *starttab = NULL, *lengthtab = NULL; + unsigned char *rlebuf = NULL; + unsigned char *lumbuf = NULL; + int rlebuflen; + Py_ssize_t goodwrite; + PyObject *retval = NULL; + + if (!PyArg_ParseTuple(args, "s#iiis:longstoimage", &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(Py_Int32); + + starttab = (Py_Int32 *)malloc(tablen); + lengthtab = (Py_Int32 *)malloc(tablen); + rlebuflen = (int) (1.05 * xsize + 10); + rlebuf = (unsigned char *)malloc(rlebuflen); + lumbuf = (unsigned char *)malloc(xsize * sizeof(Py_Int32)); + 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(Py_UInt32); + 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(Py_UInt32); + else + lptr += xsize * sizeof(Py_UInt32); + } + + 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(unsigned char *rgbptr, unsigned char *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(unsigned char *lbuf, unsigned char *rlebuf, int z, int cnt) +{ + unsigned char *iptr, *ibufend, *sptr, *optr; + short todo, cc; + Py_Int32 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(PyObject *self, PyObject *args) +{ + int order, oldorder; + + if (!PyArg_ParseTuple(args, "i:ttob", &order)) + return NULL; + oldorder = reverse_order; + reverse_order = order; + return PyInt_FromLong(oldorder); +} + +static PyMethodDef +rgbimg_methods[] = { + {"sizeofimage", sizeofimage, METH_VARARGS}, + {"longimagedata", longimagedata, METH_VARARGS}, + {"longstoimage", longstoimage, METH_VARARGS}, + {"ttob", ttob, METH_VARARGS}, + {NULL, NULL} /* sentinel */ +}; + + +PyMODINIT_FUNC +initrgbimg(void) +{ + PyObject *m, *d; + m = Py_InitModule("rgbimg", rgbimg_methods); + if (m == NULL) + return; + + if (PyErr_Warn(PyExc_DeprecationWarning, + "the rgbimg module is deprecated")) + return; + + d = PyModule_GetDict(m); + ImgfileError = PyErr_NewException("rgbimg.error", NULL, NULL); + if (ImgfileError != NULL) + PyDict_SetItemString(d, "error", ImgfileError); +} |