blob: 4ece3cc3a088e0bf58d5c4059174620cf9d5b16a [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 */
109addlongimgtag(dptr,xsize,ysize)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000110 unsigned long *dptr;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000111int xsize, ysize;
112{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000113 dptr = dptr+(xsize*ysize);
114 dptr[0] = 0x12345678;
115 dptr[1] = 0x59493333;
116 dptr[2] = 0x69434222;
117 dptr[3] = xsize;
118 dptr[4] = ysize;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000119}
120#endif
121
122/*
123 * byte order independent read/write of shorts and longs.
124 *
125 */
126static unsigned short getshort(inf)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000127 FILE *inf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000128{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000129 unsigned char buf[2];
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000130
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000131 fread(buf,2,1,inf);
132 return (buf[0]<<8)+(buf[1]<<0);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000133}
134
135static unsigned long getlong(inf)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000136 FILE *inf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000137{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000138 unsigned char buf[4];
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000139
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000140 fread(buf,4,1,inf);
141 return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000142}
143
Guido van Rossum2977e5d1996-08-19 22:02:19 +0000144static void putshort(outf,val)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000145 FILE *outf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000146unsigned short val;
147{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000148 unsigned char buf[2];
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000149
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000150 buf[0] = (val>>8);
151 buf[1] = (val>>0);
152 fwrite(buf,2,1,outf);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000153}
154
155static int putlong(outf,val)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000156 FILE *outf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000157unsigned long val;
158{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000159 unsigned char buf[4];
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000160
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000161 buf[0] = (val>>24);
162 buf[1] = (val>>16);
163 buf[2] = (val>>8);
164 buf[3] = (val>>0);
165 return fwrite(buf,4,1,outf);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000166}
167
Guido van Rossum2977e5d1996-08-19 22:02:19 +0000168static void readheader(inf,image)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000169 FILE *inf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000170IMAGE *image;
171{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000172 memset(image,0,sizeof(IMAGE));
173 image->imagic = getshort(inf);
174 image->type = getshort(inf);
175 image->dim = getshort(inf);
176 image->xsize = getshort(inf);
177 image->ysize = getshort(inf);
178 image->zsize = getshort(inf);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000179}
180
181static int writeheader(outf,image)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000182 FILE *outf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000183IMAGE *image;
184{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000185 IMAGE t;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000186
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000187 memset(&t,0,sizeof(IMAGE));
188 fwrite(&t,sizeof(IMAGE),1,outf);
189 fseek(outf,0,SEEK_SET);
190 putshort(outf,image->imagic);
191 putshort(outf,image->type);
192 putshort(outf,image->dim);
193 putshort(outf,image->xsize);
194 putshort(outf,image->ysize);
195 putshort(outf,image->zsize);
196 putlong(outf,image->min);
197 putlong(outf,image->max);
198 putlong(outf,0);
199 return fwrite("no name",8,1,outf);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000200}
201
202static int writetab(outf,tab,len)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000203 FILE *outf;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000204/*unsigned*/ long *tab;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000205int len;
206{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000207 int r = 0;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000208
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000209 while(len) {
210 r = putlong(outf,*tab++);
211 len -= 4;
212 }
213 return r;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000214}
215
Guido van Rossum2977e5d1996-08-19 22:02:19 +0000216static void readtab(inf,tab,len)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000217 FILE *inf;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000218/*unsigned*/ long *tab;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000219int len;
220{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000221 while(len) {
222 *tab++ = getlong(inf);
223 len -= 4;
224 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000225}
226
227/*
228 * sizeofimage -
229 * return the xsize and ysize of an iris image file.
230 *
231 */
Barry Warsaw7bd9fbd1996-12-11 21:33:16 +0000232static PyObject *
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000233sizeofimage(self, args)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000234 PyObject *self, *args;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000235{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000236 char *name;
237 IMAGE image;
238 FILE *inf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000239
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000240 if (!PyArg_Parse(args, "s", &name))
241 return NULL;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000242
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000243 inf = fopen(name,"r");
244 if(!inf) {
245 PyErr_SetString(ImgfileError, "can't open image file");
246 return NULL;
247 }
248 readheader(inf,&image);
249 fclose(inf);
250 if(image.imagic != IMAGIC) {
251 PyErr_SetString(ImgfileError,
252 "bad magic number in image file");
253 return NULL;
254 }
255 return Py_BuildValue("(ii)", image.xsize, image.ysize);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000256}
257
258/*
259 * longimagedata -
260 * read in a B/W RGB or RGBA iris image file and return a
261 * pointer to an array of longs.
262 *
263 */
Barry Warsaw7bd9fbd1996-12-11 21:33:16 +0000264static PyObject *
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000265longimagedata(self, args)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000266 PyObject *self, *args;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000267{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000268 char *name;
269 unsigned char *base, *lptr;
270 unsigned char *rledat, *verdat;
271 long *starttab, *lengthtab;
272 FILE *inf;
273 IMAGE image;
274 int y, z, tablen;
275 int xsize, ysize, zsize;
276 int bpp, rle, cur, badorder;
277 int rlebuflen;
278 PyObject *rv;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000279
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000280 if (!PyArg_Parse(args, "s", &name))
281 return NULL;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000282
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000283 inf = fopen(name,"r");
284 if(!inf) {
285 PyErr_SetString(ImgfileError,"can't open image file");
286 return NULL;
287 }
288 readheader(inf,&image);
289 if(image.imagic != IMAGIC) {
290 PyErr_SetString(ImgfileError,"bad magic number in image file");
291 fclose(inf);
292 return NULL;
293 }
294 rle = ISRLE(image.type);
295 bpp = BPP(image.type);
296 if(bpp != 1 ) {
297 PyErr_SetString(ImgfileError,
298 "image must have 1 byte per pix chan");
299 fclose(inf);
300 return NULL;
301 }
302 xsize = image.xsize;
303 ysize = image.ysize;
304 zsize = image.zsize;
305 if(rle) {
306 tablen = ysize*zsize*sizeof(long);
307 starttab = (long *)malloc(tablen);
308 lengthtab = (long *)malloc(tablen);
309 rlebuflen = 1.05*xsize+10;
310 rledat = (unsigned char *)malloc(rlebuflen);
311 fseek(inf,512,SEEK_SET);
312 readtab(inf,starttab,tablen);
313 readtab(inf,lengthtab,tablen);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000314
315/* check data order */
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000316 cur = 0;
317 badorder = 0;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000318 for(y=0; y<ysize; y++) {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000319 for(z=0; z<zsize; z++) {
320 if(starttab[y+z*ysize]<cur) {
321 badorder = 1;
322 break;
323 }
324 cur = starttab[y+z*ysize];
325 }
326 if(badorder)
327 break;
328 }
329
330 fseek(inf,512+2*tablen,SEEK_SET);
331 cur = 512+2*tablen;
332 rv = PyString_FromStringAndSize((char *) 0,
333 (xsize*ysize+TAGLEN)*sizeof(long));
334 if (rv == NULL) {
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000335 fclose(inf);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000336 free(lengthtab);
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000337 free(starttab);
338 free(rledat);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000339 return NULL;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000340 }
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000341 base = (unsigned char *) PyString_AsString(rv);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000342#ifdef ADD_TAGS
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000343 addlongimgtag(base,xsize,ysize);
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000344#endif
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000345 if(badorder) {
346 for(z=0; z<zsize; z++) {
347 lptr = base;
348 if (reverse_order)
349 lptr += (ysize - 1) * xsize
350 * sizeof(unsigned long);
351 for(y=0; y<ysize; y++) {
352 if(cur != starttab[y+z*ysize]) {
353 fseek(inf,starttab[y+z*ysize],
354 SEEK_SET);
355 cur = starttab[y+z*ysize];
356 }
357 if(lengthtab[y+z*ysize]>rlebuflen) {
358 PyErr_SetString(ImgfileError,
359 "rlebuf is too small - bad poop");
360 fclose(inf);
361 Py_DECREF(rv);
362 free(rledat);
363 free(starttab);
364 free(lengthtab);
365 return NULL;
366 }
367 fread(rledat,lengthtab[y+z*ysize],
368 1,inf);
369 cur += lengthtab[y+z*ysize];
370 expandrow(lptr,rledat,3-z);
371 if (reverse_order)
372 lptr -= xsize
373 * sizeof(unsigned long);
374 else
375 lptr += xsize
376 * sizeof(unsigned long);
377 }
378 }
379 } else {
380 lptr = base;
381 if (reverse_order)
382 lptr += (ysize - 1) * xsize
383 * sizeof(unsigned long);
384 for(y=0; y<ysize; y++) {
385 for(z=0; z<zsize; z++) {
386 if(cur != starttab[y+z*ysize]) {
387 fseek(inf,starttab[y+z*ysize],
388 SEEK_SET);
389 cur = starttab[y+z*ysize];
390 }
391 fread(rledat,lengthtab[y+z*ysize],
392 1,inf);
393 cur += lengthtab[y+z*ysize];
394 expandrow(lptr,rledat,3-z);
395 }
396 if (reverse_order)
397 lptr -= xsize * sizeof(unsigned long);
398 else
399 lptr += xsize * sizeof(unsigned long);
400 }
401 }
402 if(zsize == 3)
403 setalpha(base,xsize*ysize);
404 else if(zsize<3)
405 copybw((long *) base,xsize*ysize);
406 fclose(inf);
407 free(starttab);
408 free(lengthtab);
409 free(rledat);
410 return rv;
411 } else {
412 rv = PyString_FromStringAndSize((char *) 0,
413 (xsize*ysize+TAGLEN)*sizeof(long));
414 if (rv == NULL) {
415 fclose(inf);
416 return NULL;
417 }
418 base = (unsigned char *) PyString_AsString(rv);
419#ifdef ADD_TAGS
420 addlongimgtag(base,xsize,ysize);
421#endif
422 verdat = (unsigned char *)malloc(xsize);
423 fseek(inf,512,SEEK_SET);
424 for(z=0; z<zsize; z++) {
425 lptr = base;
426 if (reverse_order)
427 lptr += (ysize - 1) * xsize
428 * sizeof(unsigned long);
429 for(y=0; y<ysize; y++) {
430 fread(verdat,xsize,1,inf);
431 interleaverow(lptr,verdat,3-z,xsize);
432 if (reverse_order)
433 lptr -= xsize * sizeof(unsigned long);
434 else
435 lptr += xsize * sizeof(unsigned long);
436 }
437 }
438 if(zsize == 3)
439 setalpha(base,xsize*ysize);
440 else if(zsize<3)
441 copybw((long *) base,xsize*ysize);
442 fclose(inf);
443 free(verdat);
444 return rv;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000445 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000446}
447
448/* static utility functions for longimagedata */
449
Guido van Rossum2977e5d1996-08-19 22:02:19 +0000450static void interleaverow(lptr,cptr,z,n)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000451 unsigned char *lptr, *cptr;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000452int z, n;
453{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000454 lptr += z;
455 while(n--) {
456 *lptr = *cptr++;
457 lptr += 4;
458 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000459}
460
Guido van Rossum2977e5d1996-08-19 22:02:19 +0000461static void copybw(lptr,n)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000462 long *lptr;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000463int n;
464{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000465 while(n>=8) {
466 lptr[0] = 0xff000000+(0x010101*(lptr[0]&0xff));
467 lptr[1] = 0xff000000+(0x010101*(lptr[1]&0xff));
468 lptr[2] = 0xff000000+(0x010101*(lptr[2]&0xff));
469 lptr[3] = 0xff000000+(0x010101*(lptr[3]&0xff));
470 lptr[4] = 0xff000000+(0x010101*(lptr[4]&0xff));
471 lptr[5] = 0xff000000+(0x010101*(lptr[5]&0xff));
472 lptr[6] = 0xff000000+(0x010101*(lptr[6]&0xff));
473 lptr[7] = 0xff000000+(0x010101*(lptr[7]&0xff));
474 lptr += 8;
475 n-=8;
476 }
477 while(n--) {
478 *lptr = 0xff000000+(0x010101*(*lptr&0xff));
479 lptr++;
480 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000481}
482
Guido van Rossum2977e5d1996-08-19 22:02:19 +0000483static void setalpha(lptr,n)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000484 unsigned char *lptr;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000485{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000486 while(n>=8) {
487 lptr[0*4] = 0xff;
488 lptr[1*4] = 0xff;
489 lptr[2*4] = 0xff;
490 lptr[3*4] = 0xff;
491 lptr[4*4] = 0xff;
492 lptr[5*4] = 0xff;
493 lptr[6*4] = 0xff;
494 lptr[7*4] = 0xff;
495 lptr += 4*8;
496 n -= 8;
497 }
498 while(n--) {
499 *lptr = 0xff;
500 lptr += 4;
501 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000502}
503
Guido van Rossum2977e5d1996-08-19 22:02:19 +0000504static void expandrow(optr,iptr,z)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000505 unsigned char *optr, *iptr;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000506int z;
507{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000508 unsigned char pixel, count;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000509
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000510 optr += z;
511 while(1) {
512 pixel = *iptr++;
513 if ( !(count = (pixel & 0x7f)) )
514 return;
515 if(pixel & 0x80) {
516 while(count>=8) {
517 optr[0*4] = iptr[0];
518 optr[1*4] = iptr[1];
519 optr[2*4] = iptr[2];
520 optr[3*4] = iptr[3];
521 optr[4*4] = iptr[4];
522 optr[5*4] = iptr[5];
523 optr[6*4] = iptr[6];
524 optr[7*4] = iptr[7];
525 optr += 8*4;
526 iptr += 8;
527 count -= 8;
528 }
529 while(count--) {
530 *optr = *iptr++;
531 optr+=4;
532 }
533 } else {
534 pixel = *iptr++;
535 while(count>=8) {
536 optr[0*4] = pixel;
537 optr[1*4] = pixel;
538 optr[2*4] = pixel;
539 optr[3*4] = pixel;
540 optr[4*4] = pixel;
541 optr[5*4] = pixel;
542 optr[6*4] = pixel;
543 optr[7*4] = pixel;
544 optr += 8*4;
545 count -= 8;
546 }
547 while(count--) {
548 *optr = pixel;
549 optr+=4;
550 }
551 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000552 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000553}
554
555/*
556 * longstoimage -
557 * copy an array of longs to an iris image file. Each long
558 * represents one pixel. xsize and ysize specify the dimensions of
559 * the pixel array. zsize specifies what kind of image file to
560 * write out. if zsize is 1, the luminance of the pixels are
561 * calculated, and a sinlge channel black and white image is saved.
562 * If zsize is 3, an RGB image file is saved. If zsize is 4, an
563 * RGBA image file is saved.
564 *
565 */
Barry Warsaw7bd9fbd1996-12-11 21:33:16 +0000566static PyObject *
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000567longstoimage(self, args)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000568 PyObject *self, *args;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000569{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000570 unsigned char *lptr;
571 char *name;
572 int xsize, ysize, zsize;
573 FILE *outf;
574 IMAGE image;
575 int tablen, y, z, pos, len;
576 long *starttab, *lengthtab;
577 unsigned char *rlebuf;
578 unsigned char *lumbuf;
579 int rlebuflen, goodwrite;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000580
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000581 if (!PyArg_Parse(args, "(s#iiis)", &lptr, &len, &xsize, &ysize, &zsize,
582 &name))
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000583 return NULL;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000584
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000585 goodwrite = 1;
586 outf = fopen(name,"w");
587 if(!outf) {
588 PyErr_SetString(ImgfileError,"can't open output file");
589 return NULL;
590 }
591 tablen = ysize*zsize*sizeof(long);
592
593 starttab = (long *)malloc(tablen);
594 lengthtab = (long *)malloc(tablen);
595 rlebuflen = 1.05*xsize+10;
596 rlebuf = (unsigned char *)malloc(rlebuflen);
597 lumbuf = (unsigned char *)malloc(xsize*sizeof(long));
598
599 memset(&image,0,sizeof(IMAGE));
600 image.imagic = IMAGIC;
601 image.type = RLE(1);
602 if(zsize>1)
603 image.dim = 3;
604 else
605 image.dim = 2;
606 image.xsize = xsize;
607 image.ysize = ysize;
608 image.zsize = zsize;
609 image.min = 0;
610 image.max = 255;
611 goodwrite *= writeheader(outf,&image);
612 fseek(outf,512+2*tablen,SEEK_SET);
613 pos = 512+2*tablen;
614 if (reverse_order)
615 lptr += (ysize - 1) * xsize * sizeof(unsigned long);
616 for(y=0; y<ysize; y++) {
617 for(z=0; z<zsize; z++) {
618 if(zsize == 1) {
619 lumrow(lptr,lumbuf,xsize);
620 len = compressrow(lumbuf,rlebuf,CHANOFFSET(z),
621 xsize);
622 } else {
623 len = compressrow(lptr,rlebuf,CHANOFFSET(z),
624 xsize);
625 }
626 if(len>rlebuflen) {
627 PyErr_SetString(ImgfileError,
628 "rlebuf is too small - bad poop");
629 free(starttab);
630 free(lengthtab);
631 free(rlebuf);
632 free(lumbuf);
633 fclose(outf);
634 return NULL;
635 }
636 goodwrite *= fwrite(rlebuf,len,1,outf);
637 starttab[y+z*ysize] = pos;
638 lengthtab[y+z*ysize] = len;
639 pos += len;
640 }
641 if (reverse_order)
642 lptr -= xsize * sizeof(unsigned long);
643 else
644 lptr += xsize * sizeof(unsigned long);
645 }
646
647 fseek(outf,512,SEEK_SET);
648 goodwrite *= writetab(outf,starttab,tablen);
649 goodwrite *= writetab(outf,lengthtab,tablen);
650 free(starttab);
651 free(lengthtab);
652 free(rlebuf);
653 free(lumbuf);
654 fclose(outf);
655 if(goodwrite) {
656 Py_INCREF(Py_None);
657 return Py_None;
658 } else {
659 PyErr_SetString(ImgfileError,"not enough space for image!!");
660 return NULL;
661 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000662}
663
664/* static utility functions for longstoimage */
665
Guido van Rossum2977e5d1996-08-19 22:02:19 +0000666static void lumrow(rgbptr,lumptr,n)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000667 unsigned char *rgbptr, *lumptr;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000668int n;
669{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000670 lumptr += CHANOFFSET(0);
671 while(n--) {
672 *lumptr = ILUM(rgbptr[OFFSET_R],rgbptr[OFFSET_G],
673 rgbptr[OFFSET_B]);
674 lumptr += 4;
675 rgbptr += 4;
676 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000677}
678
679static int compressrow(lbuf,rlebuf,z,cnt)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000680 unsigned char *lbuf, *rlebuf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000681int z, cnt;
682{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000683 unsigned char *iptr, *ibufend, *sptr, *optr;
684 short todo, cc;
685 long count;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000686
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000687 lbuf += z;
688 iptr = lbuf;
689 ibufend = iptr+cnt*4;
690 optr = rlebuf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000691
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000692 while(iptr<ibufend) {
693 sptr = iptr;
694 iptr += 8;
695 while((iptr<ibufend)&& ((iptr[-8]!=iptr[-4])
696 ||(iptr[-4]!=iptr[0])))
697 iptr+=4;
698 iptr -= 8;
699 count = (iptr-sptr)/4;
700 while(count) {
701 todo = count>126 ? 126:count;
702 count -= todo;
703 *optr++ = 0x80|todo;
704 while(todo>8) {
705 optr[0] = sptr[0*4];
706 optr[1] = sptr[1*4];
707 optr[2] = sptr[2*4];
708 optr[3] = sptr[3*4];
709 optr[4] = sptr[4*4];
710 optr[5] = sptr[5*4];
711 optr[6] = sptr[6*4];
712 optr[7] = sptr[7*4];
713 optr += 8;
714 sptr += 8*4;
715 todo -= 8;
716 }
717 while(todo--) {
718 *optr++ = *sptr;
719 sptr += 4;
720 }
721 }
722 sptr = iptr;
723 cc = *iptr;
724 iptr += 4;
725 while( (iptr<ibufend) && (*iptr == cc) )
726 iptr += 4;
727 count = (iptr-sptr)/4;
728 while(count) {
729 todo = count>126 ? 126:count;
730 count -= todo;
731 *optr++ = todo;
732 *optr++ = cc;
733 }
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000734 }
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000735 *optr++ = 0;
736 return optr - (unsigned char *)rlebuf;
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000737}
738
Barry Warsaw7bd9fbd1996-12-11 21:33:16 +0000739static PyObject *
Sjoerd Mullender0d2d3971993-12-24 14:51:14 +0000740ttob(self, args)
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000741 PyObject *self;
742PyObject *args;
Sjoerd Mullender0d2d3971993-12-24 14:51:14 +0000743{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000744 int order, oldorder;
Sjoerd Mullender0d2d3971993-12-24 14:51:14 +0000745
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000746 if (!PyArg_Parse(args, "i", &order))
747 return NULL;
748 oldorder = reverse_order;
749 reverse_order = order;
750 return PyInt_FromLong(oldorder);
Sjoerd Mullender0d2d3971993-12-24 14:51:14 +0000751}
752
Barry Warsaw7bd9fbd1996-12-11 21:33:16 +0000753static PyMethodDef rgbimg_methods[] = {
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000754 {"sizeofimage", sizeofimage},
755 {"longimagedata", longimagedata},
756 {"longstoimage", longstoimage},
757 {"ttob", ttob},
758 {NULL, NULL} /* sentinel */
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000759};
760
761void
762initrgbimg()
763{
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000764 PyObject *m, *d;
765 m = Py_InitModule("rgbimg", rgbimg_methods);
766 d = PyModule_GetDict(m);
767 ImgfileError = PyString_FromString("rgbimg.error");
768 if (ImgfileError == NULL
769 || PyDict_SetItemString(d, "error", ImgfileError))
770 Py_FatalError("can't define rgbimg.error");
Sjoerd Mullenderc4f169c1993-12-21 17:06:12 +0000771}
Roger E. Masse5b0eba31997-01-03 18:51:01 +0000772
773
774
775
776
777
778
779
780
781
782
783
784