blob: 2619541502e506ebb993543728ba22a1d304c015 [file] [log] [blame]
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +00001/*
2 * fastimg -
3 * Faster reading and writing of image files.
4 *
5 * This code should work on machines with any byte order.
6 *
7 * Could someone make this run real fast using multiple processors
8 * or how about using memory mapped files to speed it up?
9 *
10 * Paul Haeberli - 1991
11 *
12 * Changed to return sizes.
13 * Sjoerd Mullender - 1993
14 * Changed to incorporate into Python.
15 * Sjoerd Mullender - 1993
16 */
Barry Warsaw7bd9fbd1996-12-11 21:33:16 +000017#include "Python.h"
18
Guido van Rossumb6775db1994-08-01 11:34:53 +000019#ifdef HAVE_UNISTD_H
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +000020#include <unistd.h>
Guido van Rossumb6775db1994-08-01 11:34:53 +000021#endif
Sjoerd Mullender92fa23f1993-12-24 10:05:51 +000022#include <string.h>
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +000023
24/*
25 * from image.h
26 *
27 */
28typedef struct {
Roger E. Masse5b0eba31997-01-03 18:51:01 +000029 unsigned short imagic; /* stuff saved on disk . . */
30 unsigned short type;
31 unsigned short dim;
32 unsigned short xsize;
33 unsigned short ysize;
34 unsigned short zsize;
35 unsigned long min;
36 unsigned long max;
37 unsigned long wastebytes;
38 char name[80];
39 unsigned long colormap;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +000040
Roger E. Masse5b0eba31997-01-03 18:51:01 +000041 long file; /* stuff used in core only */
42 unsigned short flags;
43 short dorev;
44 short x;
45 short y;
46 short z;
47 short cnt;
48 unsigned short *ptr;
49 unsigned short *base;
50 unsigned short *tmpbuf;
51 unsigned long offset;
52 unsigned long rleend; /* for rle images */
53 unsigned long *rowstart; /* for rle images */
54 long *rowsize; /* for rle images */
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +000055} IMAGE;
56
57#define IMAGIC 0732
58
59#define TYPEMASK 0xff00
60#define BPPMASK 0x00ff
61#define ITYPE_VERBATIM 0x0000
62#define ITYPE_RLE 0x0100
63#define ISRLE(type) (((type) & 0xff00) == ITYPE_RLE)
64#define ISVERBATIM(type) (((type) & 0xff00) == ITYPE_VERBATIM)
65#define BPP(type) ((type) & BPPMASK)
66#define RLE(bpp) (ITYPE_RLE | (bpp))
67#define VERBATIM(bpp) (ITYPE_VERBATIM | (bpp))
68/*
69 * end of image.h stuff
70 *
71 */
72
73#define RINTLUM (79)
74#define GINTLUM (156)
75#define BINTLUM (21)
76
77#define ILUM(r,g,b) ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8)
78
79#define OFFSET_R 3 /* this is byte order dependent */
80#define OFFSET_G 2
81#define OFFSET_B 1
82#define OFFSET_A 0
83
84#define CHANOFFSET(z) (3-(z)) /* this is byte order dependent */
85
Barry Warsaw7bd9fbd1996-12-11 21:33:16 +000086static void expandrow Py_PROTO((unsigned char *, unsigned char *, int));
87static void setalpha Py_PROTO((unsigned char *, int));
88static void copybw Py_PROTO((long *, int));
89static void interleaverow Py_PROTO((unsigned char*, unsigned char*, int, int));
90static int compressrow Py_PROTO((unsigned char *, unsigned char *, int, int));
91static void lumrow Py_PROTO((unsigned char *, unsigned char *, int));
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +000092
93#ifdef ADD_TAGS
94#define TAGLEN (5)
95#else
96#define TAGLEN (0)
97#endif
98
Barry Warsaw7bd9fbd1996-12-11 21:33:16 +000099static PyObject *ImgfileError;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000100
Sjoerd Mullender0d2d3971993-12-24 14:51:14 +0000101static int reverse_order;
102
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000103#ifdef ADD_TAGS
104/*
105 * addlongimgtag -
106 * this is used to extract image data from core dumps.
107 *
108 */
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000109static void
110addlongimgtag(dptr, xsize, ysize)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000111 unsigned long *dptr;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000112 int xsize, ysize;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000113{
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000114 dptr = dptr + (xsize * ysize);
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000115 dptr[0] = 0x12345678;
116 dptr[1] = 0x59493333;
117 dptr[2] = 0x69434222;
118 dptr[3] = xsize;
119 dptr[4] = ysize;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000120}
121#endif
122
123/*
124 * byte order independent read/write of shorts and longs.
125 *
126 */
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000127static unsigned short
128getshort(inf)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000129 FILE *inf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000130{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000131 unsigned char buf[2];
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000132
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000133 fread(buf, 2, 1, inf);
134 return (buf[0] << 8) + (buf[1] << 0);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000135}
136
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000137static unsigned long
138getlong(inf)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000139 FILE *inf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000140{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000141 unsigned char buf[4];
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000142
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000143 fread(buf, 4, 1, inf);
144 return (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + (buf[3] << 0);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000145}
146
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000147static void
148putshort(outf, val)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000149 FILE *outf;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000150 unsigned short val;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000151{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000152 unsigned char buf[2];
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000153
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000154 buf[0] = (val >> 8);
155 buf[1] = (val >> 0);
156 fwrite(buf, 2, 1, outf);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000157}
158
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000159static int
160putlong(outf, val)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000161 FILE *outf;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000162 unsigned long val;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000163{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000164 unsigned char buf[4];
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000165
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000166 buf[0] = (val >> 24);
167 buf[1] = (val >> 16);
168 buf[2] = (val >> 8);
169 buf[3] = (val >> 0);
170 return fwrite(buf, 4, 1, outf);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000171}
172
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000173static void
174readheader(inf, image)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000175 FILE *inf;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000176 IMAGE *image;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000177{
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000178 memset(image ,0, sizeof(IMAGE));
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000179 image->imagic = getshort(inf);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000180 image->type = getshort(inf);
181 image->dim = getshort(inf);
182 image->xsize = getshort(inf);
183 image->ysize = getshort(inf);
184 image->zsize = getshort(inf);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000185}
186
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000187static int
188writeheader(outf, image)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000189 FILE *outf;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000190 IMAGE *image;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000191{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000192 IMAGE t;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000193
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000194 memset(&t, 0, sizeof(IMAGE));
195 fwrite(&t, sizeof(IMAGE), 1, outf);
196 fseek(outf, 0, SEEK_SET);
197 putshort(outf, image->imagic);
198 putshort(outf, image->type);
199 putshort(outf, image->dim);
200 putshort(outf, image->xsize);
201 putshort(outf, image->ysize);
202 putshort(outf, image->zsize);
203 putlong(outf, image->min);
204 putlong(outf, image->max);
205 putlong(outf, 0);
206 return fwrite("no name", 8, 1, outf);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000207}
208
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000209static int
210writetab(outf, tab, len)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000211 FILE *outf;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000212 /*unsigned*/ long *tab;
213 int len;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000214{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000215 int r = 0;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000216
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000217 while(len) {
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000218 r = putlong(outf, *tab++);
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000219 len -= 4;
220 }
221 return r;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000222}
223
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000224static void
225readtab(inf, tab, len)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000226 FILE *inf;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000227 /*unsigned*/ long *tab;
228 int len;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000229{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000230 while(len) {
231 *tab++ = getlong(inf);
232 len -= 4;
233 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000234}
235
236/*
237 * sizeofimage -
238 * return the xsize and ysize of an iris image file.
239 *
240 */
Barry Warsaw7bd9fbd1996-12-11 21:33:16 +0000241static PyObject *
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000242sizeofimage(self, args)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000243 PyObject *self, *args;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000244{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000245 char *name;
246 IMAGE image;
247 FILE *inf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000248
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000249 if (!PyArg_Parse(args, "s", &name))
250 return NULL;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000251
Guido van Rossum56809061997-02-21 15:19:03 +0000252 inf = fopen(name, "rw");
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000253 if (!inf) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000254 PyErr_SetString(ImgfileError, "can't open image file");
255 return NULL;
256 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000257 readheader(inf, &image);
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000258 fclose(inf);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000259 if (image.imagic != IMAGIC) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000260 PyErr_SetString(ImgfileError,
261 "bad magic number in image file");
262 return NULL;
263 }
264 return Py_BuildValue("(ii)", image.xsize, image.ysize);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000265}
266
267/*
268 * longimagedata -
269 * read in a B/W RGB or RGBA iris image file and return a
270 * pointer to an array of longs.
271 *
272 */
Barry Warsaw7bd9fbd1996-12-11 21:33:16 +0000273static PyObject *
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000274longimagedata(self, args)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000275 PyObject *self, *args;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000276{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000277 char *name;
278 unsigned char *base, *lptr;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000279 unsigned char *rledat = NULL, *verdat = NULL;
280 long *starttab = NULL, *lengthtab = NULL;
281 FILE *inf = NULL;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000282 IMAGE image;
283 int y, z, tablen;
284 int xsize, ysize, zsize;
285 int bpp, rle, cur, badorder;
286 int rlebuflen;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000287 PyObject *rv = NULL;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000288
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000289 if (!PyArg_Parse(args, "s", &name))
290 return NULL;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000291
Guido van Rossum56809061997-02-21 15:19:03 +0000292 inf = fopen(name,"rb");
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000293 if (!inf) {
294 PyErr_SetString(ImgfileError, "can't open image file");
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000295 return NULL;
296 }
297 readheader(inf,&image);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000298 if (image.imagic != IMAGIC) {
299 PyErr_SetString(ImgfileError,
300 "bad magic number in image file");
301 goto finally;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000302 }
303 rle = ISRLE(image.type);
304 bpp = BPP(image.type);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000305 if (bpp != 1) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000306 PyErr_SetString(ImgfileError,
307 "image must have 1 byte per pix chan");
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000308 goto finally;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000309 }
310 xsize = image.xsize;
311 ysize = image.ysize;
312 zsize = image.zsize;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000313 if (rle) {
314 tablen = ysize * zsize * sizeof(long);
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000315 starttab = (long *)malloc(tablen);
316 lengthtab = (long *)malloc(tablen);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000317 rlebuflen = 1.05 * xsize +10;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000318 rledat = (unsigned char *)malloc(rlebuflen);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000319 if (!starttab || !lengthtab || !rledat) {
320 PyErr_NoMemory();
321 goto finally;
322 }
323
324 fseek(inf, 512, SEEK_SET);
325 readtab(inf, starttab, tablen);
326 readtab(inf, lengthtab, tablen);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000327
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000328 /* check data order */
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000329 cur = 0;
330 badorder = 0;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000331 for(y = 0; y < ysize; y++) {
332 for(z = 0; z < zsize; z++) {
333 if (starttab[y + z * ysize] < cur) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000334 badorder = 1;
335 break;
336 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000337 cur = starttab[y +z * ysize];
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000338 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000339 if (badorder)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000340 break;
341 }
342
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000343 fseek(inf, 512 + 2 * tablen, SEEK_SET);
344 cur = 512 + 2 * tablen;
345 rv = PyString_FromStringAndSize((char *)NULL,
346 (xsize * ysize + TAGLEN) * sizeof(long));
347 if (rv == NULL)
348 goto finally;
349
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000350 base = (unsigned char *) PyString_AsString(rv);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000351#ifdef ADD_TAGS
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000352 addlongimgtag(base,xsize,ysize);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000353#endif
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000354 if (badorder) {
355 for (z = 0; z < zsize; z++) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000356 lptr = base;
357 if (reverse_order)
358 lptr += (ysize - 1) * xsize
359 * sizeof(unsigned long);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000360 for (y = 0; y < ysize; y++) {
361 int idx = y + z * ysize;
362 if (cur != starttab[idx]) {
363 fseek(inf,starttab[idx],
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000364 SEEK_SET);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000365 cur = starttab[idx];
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000366 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000367 if (lengthtab[idx] > rlebuflen) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000368 PyErr_SetString(ImgfileError,
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000369 "rlebuf is too small");
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000370 Py_DECREF(rv);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000371 rv = NULL;
372 goto finally;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000373 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000374 fread(rledat, lengthtab[idx], 1, inf);
375 cur += lengthtab[idx];
376 expandrow(lptr, rledat, 3-z);
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000377 if (reverse_order)
378 lptr -= xsize
379 * sizeof(unsigned long);
380 else
381 lptr += xsize
382 * sizeof(unsigned long);
383 }
384 }
385 } else {
386 lptr = base;
387 if (reverse_order)
388 lptr += (ysize - 1) * xsize
389 * sizeof(unsigned long);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000390 for (y = 0; y < ysize; y++) {
391 for(z = 0; z < zsize; z++) {
392 int idx = y + z * ysize;
393 if (cur != starttab[idx]) {
394 fseek(inf, starttab[idx],
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000395 SEEK_SET);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000396 cur = starttab[idx];
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000397 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000398 fread(rledat, lengthtab[idx], 1, inf);
399 cur += lengthtab[idx];
400 expandrow(lptr, rledat, 3-z);
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000401 }
402 if (reverse_order)
403 lptr -= xsize * sizeof(unsigned long);
404 else
405 lptr += xsize * sizeof(unsigned long);
406 }
407 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000408 if (zsize == 3)
409 setalpha(base, xsize * ysize);
410 else if (zsize < 3)
411 copybw((long *) base, xsize * ysize);
412 }
413 else {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000414 rv = PyString_FromStringAndSize((char *) 0,
415 (xsize*ysize+TAGLEN)*sizeof(long));
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000416 if (rv == NULL)
417 goto finally;
418
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000419 base = (unsigned char *) PyString_AsString(rv);
420#ifdef ADD_TAGS
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000421 addlongimgtag(base, xsize, ysize);
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000422#endif
423 verdat = (unsigned char *)malloc(xsize);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000424 fseek(inf, 512, SEEK_SET);
425 for (z = 0; z < zsize; z++) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000426 lptr = base;
427 if (reverse_order)
428 lptr += (ysize - 1) * xsize
429 * sizeof(unsigned long);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000430 for (y = 0; y < ysize; y++) {
431 fread(verdat, xsize, 1, inf);
432 interleaverow(lptr, verdat, 3-z, xsize);
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000433 if (reverse_order)
434 lptr -= xsize * sizeof(unsigned long);
435 else
436 lptr += xsize * sizeof(unsigned long);
437 }
438 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000439 if (zsize == 3)
440 setalpha(base, xsize * ysize);
441 else if (zsize < 3)
442 copybw((long *) base, xsize * ysize);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000443 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000444 finally:
445 free(starttab);
446 free(lengthtab);
447 free(rledat);
448 free(verdat);
449 fclose(inf);
450 return rv;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000451}
452
453/* static utility functions for longimagedata */
454
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000455static void
456interleaverow(lptr, cptr, z, n)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000457 unsigned char *lptr, *cptr;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000458 int z, n;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000459{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000460 lptr += z;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000461 while (n--) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000462 *lptr = *cptr++;
463 lptr += 4;
464 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000465}
466
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000467static void
468copybw(lptr, n)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000469 long *lptr;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000470 int n;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000471{
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000472 while (n >= 8) {
473 lptr[0] = 0xff000000 + (0x010101 * (lptr[0] & 0xff));
474 lptr[1] = 0xff000000 + (0x010101 * (lptr[1] & 0xff));
475 lptr[2] = 0xff000000 + (0x010101 * (lptr[2] & 0xff));
476 lptr[3] = 0xff000000 + (0x010101 * (lptr[3] & 0xff));
477 lptr[4] = 0xff000000 + (0x010101 * (lptr[4] & 0xff));
478 lptr[5] = 0xff000000 + (0x010101 * (lptr[5] & 0xff));
479 lptr[6] = 0xff000000 + (0x010101 * (lptr[6] & 0xff));
480 lptr[7] = 0xff000000 + (0x010101 * (lptr[7] & 0xff));
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000481 lptr += 8;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000482 n -= 8;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000483 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000484 while (n--) {
485 *lptr = 0xff000000 + (0x010101 * (*lptr&0xff));
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000486 lptr++;
487 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000488}
489
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000490static void
491setalpha(lptr, n)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000492 unsigned char *lptr;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000493{
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000494 while (n >= 8) {
495 lptr[0 * 4] = 0xff;
496 lptr[1 * 4] = 0xff;
497 lptr[2 * 4] = 0xff;
498 lptr[3 * 4] = 0xff;
499 lptr[4 * 4] = 0xff;
500 lptr[5 * 4] = 0xff;
501 lptr[6 * 4] = 0xff;
502 lptr[7 * 4] = 0xff;
503 lptr += 4 * 8;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000504 n -= 8;
505 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000506 while (n--) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000507 *lptr = 0xff;
508 lptr += 4;
509 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000510}
511
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000512static void
513expandrow(optr, iptr, z)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000514 unsigned char *optr, *iptr;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000515 int z;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000516{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000517 unsigned char pixel, count;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000518
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000519 optr += z;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000520 while (1) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000521 pixel = *iptr++;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000522 if (!(count = (pixel & 0x7f)))
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000523 return;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000524 if (pixel & 0x80) {
525 while (count >= 8) {
526 optr[0 * 4] = iptr[0];
527 optr[1 * 4] = iptr[1];
528 optr[2 * 4] = iptr[2];
529 optr[3 * 4] = iptr[3];
530 optr[4 * 4] = iptr[4];
531 optr[5 * 4] = iptr[5];
532 optr[6 * 4] = iptr[6];
533 optr[7 * 4] = iptr[7];
534 optr += 8 * 4;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000535 iptr += 8;
536 count -= 8;
537 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000538 while (count--) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000539 *optr = *iptr++;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000540 optr += 4;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000541 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000542 }
543 else {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000544 pixel = *iptr++;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000545 while (count >= 8) {
546 optr[0 * 4] = pixel;
547 optr[1 * 4] = pixel;
548 optr[2 * 4] = pixel;
549 optr[3 * 4] = pixel;
550 optr[4 * 4] = pixel;
551 optr[5 * 4] = pixel;
552 optr[6 * 4] = pixel;
553 optr[7 * 4] = pixel;
554 optr += 8 * 4;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000555 count -= 8;
556 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000557 while (count--) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000558 *optr = pixel;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000559 optr += 4;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000560 }
561 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000562 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000563}
564
565/*
566 * longstoimage -
567 * copy an array of longs to an iris image file. Each long
568 * represents one pixel. xsize and ysize specify the dimensions of
569 * the pixel array. zsize specifies what kind of image file to
570 * write out. if zsize is 1, the luminance of the pixels are
571 * calculated, and a sinlge channel black and white image is saved.
572 * If zsize is 3, an RGB image file is saved. If zsize is 4, an
573 * RGBA image file is saved.
574 *
575 */
Barry Warsaw7bd9fbd1996-12-11 21:33:16 +0000576static PyObject *
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000577longstoimage(self, args)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000578 PyObject *self, *args;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000579{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000580 unsigned char *lptr;
581 char *name;
582 int xsize, ysize, zsize;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000583 FILE *outf = NULL;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000584 IMAGE image;
585 int tablen, y, z, pos, len;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000586 long *starttab = NULL, *lengthtab = NULL;
587 unsigned char *rlebuf = NULL;
588 unsigned char *lumbuf = NULL;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000589 int rlebuflen, goodwrite;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000590 PyObject *retval = NULL;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000591
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000592 if (!PyArg_Parse(args, "(s#iiis)", &lptr, &len, &xsize, &ysize, &zsize,
593 &name))
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000594 return NULL;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000595
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000596 goodwrite = 1;
Guido van Rossum56809061997-02-21 15:19:03 +0000597 outf = fopen(name, "wb");
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000598 if (!outf) {
599 PyErr_SetString(ImgfileError, "can't open output file");
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000600 return NULL;
601 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000602 tablen = ysize * zsize * sizeof(long);
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000603
604 starttab = (long *)malloc(tablen);
605 lengthtab = (long *)malloc(tablen);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000606 rlebuflen = 1.05 * xsize + 10;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000607 rlebuf = (unsigned char *)malloc(rlebuflen);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000608 lumbuf = (unsigned char *)malloc(xsize * sizeof(long));
609 if (!starttab || !lengthtab || !rlebuf || !lumbuf) {
610 PyErr_NoMemory();
611 goto finally;
612 }
613
614 memset(&image, 0, sizeof(IMAGE));
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000615 image.imagic = IMAGIC;
616 image.type = RLE(1);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000617 if (zsize>1)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000618 image.dim = 3;
619 else
620 image.dim = 2;
621 image.xsize = xsize;
622 image.ysize = ysize;
623 image.zsize = zsize;
624 image.min = 0;
625 image.max = 255;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000626 goodwrite *= writeheader(outf, &image);
627 pos = 512 + 2 * tablen;
628 fseek(outf, pos, SEEK_SET);
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000629 if (reverse_order)
630 lptr += (ysize - 1) * xsize * sizeof(unsigned long);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000631 for (y = 0; y < ysize; y++) {
632 for (z = 0; z < zsize; z++) {
633 if (zsize == 1) {
634 lumrow(lptr, lumbuf, xsize);
635 len = compressrow(lumbuf, rlebuf,
636 CHANOFFSET(z), xsize);
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000637 } else {
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000638 len = compressrow(lptr, rlebuf,
639 CHANOFFSET(z), xsize);
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000640 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000641 if(len > rlebuflen) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000642 PyErr_SetString(ImgfileError,
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000643 "rlebuf is too small");
644 goto finally;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000645 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000646 goodwrite *= fwrite(rlebuf, len, 1, outf);
647 starttab[y + z * ysize] = pos;
648 lengthtab[y + z * ysize] = len;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000649 pos += len;
650 }
651 if (reverse_order)
652 lptr -= xsize * sizeof(unsigned long);
653 else
654 lptr += xsize * sizeof(unsigned long);
655 }
656
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000657 fseek(outf, 512, SEEK_SET);
658 goodwrite *= writetab(outf, starttab, tablen);
659 goodwrite *= writetab(outf, lengthtab, tablen);
660 if (goodwrite) {
661 Py_INCREF(Py_None);
662 retval = Py_None;
663 } else
664 PyErr_SetString(ImgfileError, "not enough space for image");
665
666 finally:
667 fclose(outf);
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000668 free(starttab);
669 free(lengthtab);
670 free(rlebuf);
671 free(lumbuf);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000672 return retval;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000673}
674
675/* static utility functions for longstoimage */
676
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000677static void
678lumrow(rgbptr, lumptr, n)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000679 unsigned char *rgbptr, *lumptr;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000680 int n;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000681{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000682 lumptr += CHANOFFSET(0);
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000683 while (n--) {
684 *lumptr = ILUM(rgbptr[OFFSET_R],
685 rgbptr[OFFSET_G],
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000686 rgbptr[OFFSET_B]);
687 lumptr += 4;
688 rgbptr += 4;
689 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000690}
691
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000692static int
693compressrow(lbuf, rlebuf, z, cnt)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000694 unsigned char *lbuf, *rlebuf;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000695 int z, cnt;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000696{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000697 unsigned char *iptr, *ibufend, *sptr, *optr;
698 short todo, cc;
699 long count;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000700
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000701 lbuf += z;
702 iptr = lbuf;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000703 ibufend = iptr + cnt * 4;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000704 optr = rlebuf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000705
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000706 while(iptr < ibufend) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000707 sptr = iptr;
708 iptr += 8;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000709 while ((iptr<ibufend) &&
710 ((iptr[-8]!=iptr[-4]) ||(iptr[-4]!=iptr[0])))
711 {
712 iptr += 4;
713 }
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000714 iptr -= 8;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000715 count = (iptr - sptr) / 4;
716 while (count) {
717 todo = count > 126 ? 126 : count;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000718 count -= todo;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000719 *optr++ = 0x80 | todo;
720 while (todo > 8) {
721 optr[0] = sptr[0 * 4];
722 optr[1] = sptr[1 * 4];
723 optr[2] = sptr[2 * 4];
724 optr[3] = sptr[3 * 4];
725 optr[4] = sptr[4 * 4];
726 optr[5] = sptr[5 * 4];
727 optr[6] = sptr[6 * 4];
728 optr[7] = sptr[7 * 4];
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000729 optr += 8;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000730 sptr += 8 * 4;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000731 todo -= 8;
732 }
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000733 while (todo--) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000734 *optr++ = *sptr;
735 sptr += 4;
736 }
737 }
738 sptr = iptr;
739 cc = *iptr;
740 iptr += 4;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000741 while ((iptr < ibufend) && (*iptr == cc))
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000742 iptr += 4;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000743 count = (iptr - sptr) / 4;
744 while (count) {
745 todo = count > 126 ? 126 : count;
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000746 count -= todo;
747 *optr++ = todo;
748 *optr++ = cc;
749 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000750 }
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000751 *optr++ = 0;
752 return optr - (unsigned char *)rlebuf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000753}
754
Barry Warsaw7bd9fbd1996-12-11 21:33:16 +0000755static PyObject *
Sjoerd Mullender0d2d3971993-12-24 14:51:14 +0000756ttob(self, args)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000757 PyObject *self;
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000758 PyObject *args;
Sjoerd Mullender0d2d3971993-12-24 14:51:14 +0000759{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000760 int order, oldorder;
Sjoerd Mullender0d2d3971993-12-24 14:51:14 +0000761
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000762 if (!PyArg_Parse(args, "i", &order))
763 return NULL;
764 oldorder = reverse_order;
765 reverse_order = order;
766 return PyInt_FromLong(oldorder);
Sjoerd Mullender0d2d3971993-12-24 14:51:14 +0000767}
768
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000769static PyMethodDef
770rgbimg_methods[] = {
771 {"sizeofimage", sizeofimage},
772 {"longimagedata", longimagedata},
773 {"longstoimage", longstoimage},
774 {"ttob", ttob},
775 {NULL, NULL} /* sentinel */
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000776};
777
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000778
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000779void
780initrgbimg()
781{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000782 PyObject *m, *d;
783 m = Py_InitModule("rgbimg", rgbimg_methods);
784 d = PyModule_GetDict(m);
785 ImgfileError = PyString_FromString("rgbimg.error");
Barry Warsaw2dc8c2c1997-01-09 22:29:12 +0000786 if (ImgfileError)
787 PyDict_SetItemString(d, "error", ImgfileError);
788 if (PyErr_Occurred())
789 Py_FatalError("can't initialize rgbimg module");
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000790}