3 * Faster reading and writing of image files.
5 * This code should work on machines with any byte order.
7 * Could someone make this run real fast using multiple processors
8 * or how about using memory mapped files to speed it up?
10 * Paul Haeberli - 1991
12 * Changed to return sizes.
13 * Sjoerd Mullender - 1993
14 * Changed to incorporate into Python.
15 * Sjoerd Mullender - 1993
17 #include "allobjects.h"
18 #include "modsupport.h"
27 unsigned short imagic
; /* stuff saved on disk . . */
35 unsigned long wastebytes
;
37 unsigned long colormap
;
39 long file
; /* stuff used in core only */
48 unsigned short *tmpbuf
;
50 unsigned long rleend
; /* for rle images */
51 unsigned long *rowstart
; /* for rle images */
52 long *rowsize
; /* for rle images */
57 #define TYPEMASK 0xff00
58 #define BPPMASK 0x00ff
59 #define ITYPE_VERBATIM 0x0000
60 #define ITYPE_RLE 0x0100
61 #define ISRLE(type) (((type) & 0xff00) == ITYPE_RLE)
62 #define ISVERBATIM(type) (((type) & 0xff00) == ITYPE_VERBATIM)
63 #define BPP(type) ((type) & BPPMASK)
64 #define RLE(bpp) (ITYPE_RLE | (bpp))
65 #define VERBATIM(bpp) (ITYPE_VERBATIM | (bpp))
67 * end of image.h stuff
75 #define ILUM(r,g,b) ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8)
77 #define OFFSET_R 3 /* this is byte order dependent */
82 #define CHANOFFSET(z) (3-(z)) /* this is byte order dependent */
84 static expandrow
PROTO((unsigned char *, unsigned char *, int));
85 static setalpha
PROTO((unsigned char *, int));
86 static copybw
PROTO((long *, int));
87 static interleaverow
PROTO((unsigned char *, unsigned char *, int, int));
88 static int compressrow
PROTO((unsigned char *, unsigned char *, int, int));
89 static lumrow
PROTO((unsigned char *, unsigned char *, int));
97 static object
*ImgfileError
;
99 static int reverse_order
;
104 * this is used to extract image data from core dumps.
107 addlongimgtag(dptr
,xsize
,ysize
)
111 dptr
= dptr
+(xsize
*ysize
);
112 dptr
[0] = 0x12345678;
113 dptr
[1] = 0x59493333;
114 dptr
[2] = 0x69434222;
121 * byte order independent read/write of shorts and longs.
124 static unsigned short getshort(inf
)
127 unsigned char buf
[2];
130 return (buf
[0]<<8)+(buf
[1]<<0);
133 static unsigned long getlong(inf
)
136 unsigned char buf
[4];
139 return (buf
[0]<<24)+(buf
[1]<<16)+(buf
[2]<<8)+(buf
[3]<<0);
142 static putshort(outf
,val
)
146 unsigned char buf
[2];
150 fwrite(buf
,2,1,outf
);
153 static int putlong(outf
,val
)
157 unsigned char buf
[4];
163 return fwrite(buf
,4,1,outf
);
166 static readheader(inf
,image
)
170 memset(image
,0,sizeof(IMAGE
));
171 image
->imagic
= getshort(inf
);
172 image
->type
= getshort(inf
);
173 image
->dim
= getshort(inf
);
174 image
->xsize
= getshort(inf
);
175 image
->ysize
= getshort(inf
);
176 image
->zsize
= getshort(inf
);
179 static int writeheader(outf
,image
)
185 memset(&t
,0,sizeof(IMAGE
));
186 fwrite(&t
,sizeof(IMAGE
),1,outf
);
187 fseek(outf
,0,SEEK_SET
);
188 putshort(outf
,image
->imagic
);
189 putshort(outf
,image
->type
);
190 putshort(outf
,image
->dim
);
191 putshort(outf
,image
->xsize
);
192 putshort(outf
,image
->ysize
);
193 putshort(outf
,image
->zsize
);
194 putlong(outf
,image
->min
);
195 putlong(outf
,image
->max
);
197 return fwrite("no name",8,1,outf
);
200 static int writetab(outf
,tab
,len
)
208 r
= putlong(outf
,*tab
++);
214 static readtab(inf
,tab
,len
)
220 *tab
++ = getlong(inf
);
227 * return the xsize and ysize of an iris image file.
231 sizeofimage(self
, args
)
238 if (!getargs(args
, "s", &name
))
241 inf
= fopen(name
,"r");
243 err_setstr(ImgfileError
, "can't open image file");
246 readheader(inf
,&image
);
248 if(image
.imagic
!= IMAGIC
) {
249 err_setstr(ImgfileError
, "bad magic number in image file");
252 return mkvalue("(ii)", image
.xsize
, image
.ysize
);
257 * read in a B/W RGB or RGBA iris image file and return a
258 * pointer to an array of longs.
262 longimagedata(self
, args
)
266 unsigned char *base
, *lptr
;
267 unsigned char *rledat
, *verdat
;
268 long *starttab
, *lengthtab
;
271 int y
, z
, pos
, len
, tablen
;
272 int xsize
, ysize
, zsize
;
273 int bpp
, rle
, cur
, badorder
;
277 if (!getargs(args
, "s", &name
))
280 inf
= fopen(name
,"r");
282 err_setstr(ImgfileError
,"can't open image file");
285 readheader(inf
,&image
);
286 if(image
.imagic
!= IMAGIC
) {
287 err_setstr(ImgfileError
,"bad magic number in image file");
291 rle
= ISRLE(image
.type
);
292 bpp
= BPP(image
.type
);
294 err_setstr(ImgfileError
,"image must have 1 byte per pix chan");
302 tablen
= ysize
*zsize
*sizeof(long);
303 starttab
= (long *)malloc(tablen
);
304 lengthtab
= (long *)malloc(tablen
);
305 rlebuflen
= 1.05*xsize
+10;
306 rledat
= (unsigned char *)malloc(rlebuflen
);
307 fseek(inf
,512,SEEK_SET
);
308 readtab(inf
,starttab
,tablen
);
309 readtab(inf
,lengthtab
,tablen
);
311 /* check data order */
314 for(y
=0; y
<ysize
; y
++) {
315 for(z
=0; z
<zsize
; z
++) {
316 if(starttab
[y
+z
*ysize
]<cur
) {
320 cur
= starttab
[y
+z
*ysize
];
326 fseek(inf
,512+2*tablen
,SEEK_SET
);
328 rv
= newsizedstringobject((char *) 0,
329 (xsize
*ysize
+TAGLEN
)*sizeof(long));
337 base
= (unsigned char *) getstringvalue(rv
);
339 addlongimgtag(base
,xsize
,ysize
);
342 for(z
=0; z
<zsize
; z
++) {
345 lptr
+= (ysize
- 1) * xsize
* sizeof(unsigned long);
346 for(y
=0; y
<ysize
; y
++) {
347 if(cur
!= starttab
[y
+z
*ysize
]) {
348 fseek(inf
,starttab
[y
+z
*ysize
],SEEK_SET
);
349 cur
= starttab
[y
+z
*ysize
];
351 if(lengthtab
[y
+z
*ysize
]>rlebuflen
) {
352 err_setstr(ImgfileError
,"rlebuf is too small - bad poop");
360 fread(rledat
,lengthtab
[y
+z
*ysize
],1,inf
);
361 cur
+= lengthtab
[y
+z
*ysize
];
362 expandrow(lptr
,rledat
,3-z
);
364 lptr
-= xsize
* sizeof(unsigned long);
366 lptr
+= xsize
* sizeof(unsigned long);
372 lptr
+= (ysize
- 1) * xsize
* sizeof(unsigned long);
373 for(y
=0; y
<ysize
; y
++) {
374 for(z
=0; z
<zsize
; z
++) {
375 if(cur
!= starttab
[y
+z
*ysize
]) {
376 fseek(inf
,starttab
[y
+z
*ysize
],SEEK_SET
);
377 cur
= starttab
[y
+z
*ysize
];
379 fread(rledat
,lengthtab
[y
+z
*ysize
],1,inf
);
380 cur
+= lengthtab
[y
+z
*ysize
];
381 expandrow(lptr
,rledat
,3-z
);
384 lptr
-= xsize
* sizeof(unsigned long);
386 lptr
+= xsize
* sizeof(unsigned long);
390 setalpha(base
,xsize
*ysize
);
392 copybw((long *) base
,xsize
*ysize
);
399 rv
= newsizedstringobject((char *) 0,
400 (xsize
*ysize
+TAGLEN
)*sizeof(long));
405 base
= (unsigned char *) getstringvalue(rv
);
407 addlongimgtag(base
,xsize
,ysize
);
409 verdat
= (unsigned char *)malloc(xsize
);
410 fseek(inf
,512,SEEK_SET
);
411 for(z
=0; z
<zsize
; z
++) {
414 lptr
+= (ysize
- 1) * xsize
* sizeof(unsigned long);
415 for(y
=0; y
<ysize
; y
++) {
416 fread(verdat
,xsize
,1,inf
);
417 interleaverow(lptr
,verdat
,3-z
,xsize
);
419 lptr
-= xsize
* sizeof(unsigned long);
421 lptr
+= xsize
* sizeof(unsigned long);
425 setalpha(base
,xsize
*ysize
);
427 copybw((long *) base
,xsize
*ysize
);
434 /* static utility functions for longimagedata */
436 static interleaverow(lptr
,cptr
,z
,n
)
437 unsigned char *lptr
, *cptr
;
447 static copybw(lptr
,n
)
452 lptr
[0] = 0xff000000+(0x010101*(lptr
[0]&0xff));
453 lptr
[1] = 0xff000000+(0x010101*(lptr
[1]&0xff));
454 lptr
[2] = 0xff000000+(0x010101*(lptr
[2]&0xff));
455 lptr
[3] = 0xff000000+(0x010101*(lptr
[3]&0xff));
456 lptr
[4] = 0xff000000+(0x010101*(lptr
[4]&0xff));
457 lptr
[5] = 0xff000000+(0x010101*(lptr
[5]&0xff));
458 lptr
[6] = 0xff000000+(0x010101*(lptr
[6]&0xff));
459 lptr
[7] = 0xff000000+(0x010101*(lptr
[7]&0xff));
464 *lptr
= 0xff000000+(0x010101*(*lptr
&0xff));
469 static setalpha(lptr
,n
)
490 static expandrow(optr
,iptr
,z
)
491 unsigned char *optr
, *iptr
;
494 unsigned char pixel
, count
;
499 if ( !(count
= (pixel
& 0x7f)) )
543 * copy an array of longs to an iris image file. Each long
544 * represents one pixel. xsize and ysize specify the dimensions of
545 * the pixel array. zsize specifies what kind of image file to
546 * write out. if zsize is 1, the luminance of the pixels are
547 * calculated, and a sinlge channel black and white image is saved.
548 * If zsize is 3, an RGB image file is saved. If zsize is 4, an
549 * RGBA image file is saved.
553 longstoimage(self
, args
)
558 int xsize
, ysize
, zsize
;
561 int tablen
, y
, z
, pos
, len
;
562 long *starttab
, *lengthtab
;
563 unsigned char *rlebuf
;
564 unsigned char *lumbuf
;
565 int rlebuflen
, goodwrite
;
567 if (!getargs(args
, "(s#iiis)", &lptr
, &len
, &xsize
, &ysize
, &zsize
, &name
))
571 outf
= fopen(name
,"w");
573 err_setstr(ImgfileError
,"can't open output file");
576 tablen
= ysize
*zsize
*sizeof(long);
578 starttab
= (long *)malloc(tablen
);
579 lengthtab
= (long *)malloc(tablen
);
580 rlebuflen
= 1.05*xsize
+10;
581 rlebuf
= (unsigned char *)malloc(rlebuflen
);
582 lumbuf
= (unsigned char *)malloc(xsize
*sizeof(long));
584 memset(&image
,0,sizeof(IMAGE
));
585 image
.imagic
= IMAGIC
;
596 goodwrite
*= writeheader(outf
,&image
);
597 fseek(outf
,512+2*tablen
,SEEK_SET
);
600 lptr
+= (ysize
- 1) * xsize
* sizeof(unsigned long);
601 for(y
=0; y
<ysize
; y
++) {
602 for(z
=0; z
<zsize
; z
++) {
604 lumrow(lptr
,lumbuf
,xsize
);
605 len
= compressrow(lumbuf
,rlebuf
,CHANOFFSET(z
),xsize
);
607 len
= compressrow(lptr
,rlebuf
,CHANOFFSET(z
),xsize
);
610 err_setstr(ImgfileError
,"rlebuf is too small - bad poop");
618 goodwrite
*= fwrite(rlebuf
,len
,1,outf
);
619 starttab
[y
+z
*ysize
] = pos
;
620 lengthtab
[y
+z
*ysize
] = len
;
624 lptr
-= xsize
* sizeof(unsigned long);
626 lptr
+= xsize
* sizeof(unsigned long);
629 fseek(outf
,512,SEEK_SET
);
630 goodwrite
*= writetab(outf
,starttab
,tablen
);
631 goodwrite
*= writetab(outf
,lengthtab
,tablen
);
641 err_setstr(ImgfileError
,"not enough space for image!!");
646 /* static utility functions for longstoimage */
648 static lumrow(rgbptr
,lumptr
,n
)
649 unsigned char *rgbptr
, *lumptr
;
652 lumptr
+= CHANOFFSET(0);
654 *lumptr
= ILUM(rgbptr
[OFFSET_R
],rgbptr
[OFFSET_G
],rgbptr
[OFFSET_B
]);
660 static int compressrow(lbuf
,rlebuf
,z
,cnt
)
661 unsigned char *lbuf
, *rlebuf
;
664 unsigned char *iptr
, *ibufend
, *sptr
, *optr
;
670 ibufend
= iptr
+cnt
*4;
673 while(iptr
<ibufend
) {
676 while((iptr
<ibufend
)&& ((iptr
[-8]!=iptr
[-4])||(iptr
[-4]!=iptr
[0])))
679 count
= (iptr
-sptr
)/4;
681 todo
= count
>126 ? 126:count
;
705 while( (iptr
<ibufend
) && (*iptr
== cc
) )
707 count
= (iptr
-sptr
)/4;
709 todo
= count
>126 ? 126:count
;
716 return optr
- (unsigned char *)rlebuf
;
726 if (!getargs(args
, "d", &order
))
728 oldorder
= reverse_order
;
729 reverse_order
= order
;
730 return newintobject(oldorder
);
733 static struct methodlist rgbimg_methods
[] = {
734 {"sizeofimage", sizeofimage
},
735 {"longimagedata", longimagedata
},
736 {"longstoimage", longstoimage
},
738 {NULL
, NULL
} /* sentinel */
745 m
= initmodule("rgbimg", rgbimg_methods
);
746 d
= getmoduledict(m
);
747 ImgfileError
= newstringobject("rgbimg,error");
748 if (ImgfileError
== NULL
|| dictinsert(d
, "error", ImgfileError
))
749 fatal("can't define rgbimg.error");