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
21 typedef unsigned int Py_UInt32
;
24 typedef long Py_Int32
;
25 typedef unsigned long Py_UInt32
;
27 #error "No 4-byte integral type"
41 unsigned short imagic
; /* stuff saved on disk . . */
53 Py_Int32 file
; /* stuff used in core only */
62 unsigned short *tmpbuf
;
64 Py_UInt32 rleend
; /* for rle images */
65 Py_UInt32
*rowstart
; /* for rle images */
66 Py_Int32
*rowsize
; /* for rle images */
71 #define TYPEMASK 0xff00
72 #define BPPMASK 0x00ff
73 #define ITYPE_VERBATIM 0x0000
74 #define ITYPE_RLE 0x0100
75 #define ISRLE(type) (((type) & 0xff00) == ITYPE_RLE)
76 #define ISVERBATIM(type) (((type) & 0xff00) == ITYPE_VERBATIM)
77 #define BPP(type) ((type) & BPPMASK)
78 #define RLE(bpp) (ITYPE_RLE | (bpp))
79 #define VERBATIM(bpp) (ITYPE_VERBATIM | (bpp))
81 * end of image.h stuff
89 #define ILUM(r,g,b) ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8)
91 #define OFFSET_R 3 /* this is byte order dependent */
96 #define CHANOFFSET(z) (3-(z)) /* this is byte order dependent */
98 static void expandrow
Py_PROTO((unsigned char *, unsigned char *, int));
99 static void setalpha
Py_PROTO((unsigned char *, int));
100 static void copybw
Py_PROTO((Py_Int32
*, int));
101 static void interleaverow
Py_PROTO((unsigned char*, unsigned char*, int, int));
102 static int compressrow
Py_PROTO((unsigned char *, unsigned char *, int, int));
103 static void lumrow
Py_PROTO((unsigned char *, unsigned char *, int));
111 static PyObject
*ImgfileError
;
113 static int reverse_order
;
118 * this is used to extract image data from core dumps.
122 addlongimgtag(dptr
, xsize
, ysize
)
126 dptr
= dptr
+ (xsize
* ysize
);
127 dptr
[0] = 0x12345678;
128 dptr
[1] = 0x59493333;
129 dptr
[2] = 0x69434222;
136 * byte order independent read/write of shorts and longs.
139 static unsigned short
143 unsigned char buf
[2];
145 fread(buf
, 2, 1, inf
);
146 return (buf
[0] << 8) + (buf
[1] << 0);
153 unsigned char buf
[4];
155 fread(buf
, 4, 1, inf
);
156 return (buf
[0] << 24) + (buf
[1] << 16) + (buf
[2] << 8) + (buf
[3] << 0);
164 unsigned char buf
[2];
168 fwrite(buf
, 2, 1, outf
);
176 unsigned char buf
[4];
178 buf
[0] = (unsigned char) (val
>> 24);
179 buf
[1] = (unsigned char) (val
>> 16);
180 buf
[2] = (unsigned char) (val
>> 8);
181 buf
[3] = (unsigned char) (val
>> 0);
182 return fwrite(buf
, 4, 1, outf
);
186 readheader(inf
, image
)
190 memset(image
,0, sizeof(IMAGE
));
191 image
->imagic
= getshort(inf
);
192 image
->type
= getshort(inf
);
193 image
->dim
= getshort(inf
);
194 image
->xsize
= getshort(inf
);
195 image
->ysize
= getshort(inf
);
196 image
->zsize
= getshort(inf
);
200 writeheader(outf
, image
)
206 memset(&t
, 0, sizeof(IMAGE
));
207 fwrite(&t
, sizeof(IMAGE
), 1, outf
);
208 fseek(outf
, 0, SEEK_SET
);
209 putshort(outf
, image
->imagic
);
210 putshort(outf
, image
->type
);
211 putshort(outf
, image
->dim
);
212 putshort(outf
, image
->xsize
);
213 putshort(outf
, image
->ysize
);
214 putshort(outf
, image
->zsize
);
215 putlong(outf
, image
->min
);
216 putlong(outf
, image
->max
);
218 return fwrite("no name", 8, 1, outf
);
222 writetab(outf
, tab
, len
)
224 /*unsigned*/ Py_Int32
*tab
;
230 r
= putlong(outf
, *tab
++);
237 readtab(inf
, tab
, len
)
239 /*unsigned*/ Py_Int32
*tab
;
243 *tab
++ = getlong(inf
);
250 * return the xsize and ysize of an iris image file.
254 sizeofimage(self
, args
)
255 PyObject
*self
, *args
;
261 if (!PyArg_Parse(args
, "s", &name
))
264 inf
= fopen(name
, "rb");
266 PyErr_SetString(ImgfileError
, "can't open image file");
269 readheader(inf
, &image
);
271 if (image
.imagic
!= IMAGIC
) {
272 PyErr_SetString(ImgfileError
,
273 "bad magic number in image file");
276 return Py_BuildValue("(ii)", image
.xsize
, image
.ysize
);
281 * read in a B/W RGB or RGBA iris image file and return a
282 * pointer to an array of longs.
286 longimagedata(self
, args
)
287 PyObject
*self
, *args
;
290 unsigned char *base
, *lptr
;
291 unsigned char *rledat
= NULL
, *verdat
= NULL
;
292 Py_Int32
*starttab
= NULL
, *lengthtab
= NULL
;
296 int xsize
, ysize
, zsize
;
297 int bpp
, rle
, cur
, badorder
;
301 if (!PyArg_Parse(args
, "s", &name
))
304 inf
= fopen(name
,"rb");
306 PyErr_SetString(ImgfileError
, "can't open image file");
309 readheader(inf
,&image
);
310 if (image
.imagic
!= IMAGIC
) {
311 PyErr_SetString(ImgfileError
,
312 "bad magic number in image file");
315 rle
= ISRLE(image
.type
);
316 bpp
= BPP(image
.type
);
318 PyErr_SetString(ImgfileError
,
319 "image must have 1 byte per pix chan");
326 tablen
= ysize
* zsize
* sizeof(Py_Int32
);
327 starttab
= (Py_Int32
*)malloc(tablen
);
328 lengthtab
= (Py_Int32
*)malloc(tablen
);
329 rlebuflen
= (int) (1.05 * xsize
+10);
330 rledat
= (unsigned char *)malloc(rlebuflen
);
331 if (!starttab
|| !lengthtab
|| !rledat
) {
336 fseek(inf
, 512, SEEK_SET
);
337 readtab(inf
, starttab
, ysize
*zsize
);
338 readtab(inf
, lengthtab
, ysize
*zsize
);
340 /* check data order */
343 for(y
= 0; y
< ysize
; y
++) {
344 for(z
= 0; z
< zsize
; z
++) {
345 if (starttab
[y
+ z
* ysize
] < cur
) {
349 cur
= starttab
[y
+z
* ysize
];
355 fseek(inf
, 512 + 2 * tablen
, SEEK_SET
);
356 cur
= 512 + 2 * tablen
;
357 rv
= PyString_FromStringAndSize((char *)NULL
,
358 (xsize
* ysize
+ TAGLEN
) * sizeof(Py_Int32
));
362 base
= (unsigned char *) PyString_AsString(rv
);
364 addlongimgtag(base
,xsize
,ysize
);
367 for (z
= 0; z
< zsize
; z
++) {
370 lptr
+= (ysize
- 1) * xsize
372 for (y
= 0; y
< ysize
; y
++) {
373 int idx
= y
+ z
* ysize
;
374 if (cur
!= starttab
[idx
]) {
375 fseek(inf
,starttab
[idx
],
379 if (lengthtab
[idx
] > rlebuflen
) {
380 PyErr_SetString(ImgfileError
,
381 "rlebuf is too small");
386 fread(rledat
, lengthtab
[idx
], 1, inf
);
387 cur
+= lengthtab
[idx
];
388 expandrow(lptr
, rledat
, 3-z
);
400 lptr
+= (ysize
- 1) * xsize
402 for (y
= 0; y
< ysize
; y
++) {
403 for(z
= 0; z
< zsize
; z
++) {
404 int idx
= y
+ z
* ysize
;
405 if (cur
!= starttab
[idx
]) {
406 fseek(inf
, starttab
[idx
],
410 fread(rledat
, lengthtab
[idx
], 1, inf
);
411 cur
+= lengthtab
[idx
];
412 expandrow(lptr
, rledat
, 3-z
);
415 lptr
-= xsize
* sizeof(Py_UInt32
);
417 lptr
+= xsize
* sizeof(Py_UInt32
);
421 setalpha(base
, xsize
* ysize
);
423 copybw((Py_Int32
*) base
, xsize
* ysize
);
426 rv
= PyString_FromStringAndSize((char *) 0,
427 (xsize
*ysize
+TAGLEN
)*sizeof(Py_Int32
));
431 base
= (unsigned char *) PyString_AsString(rv
);
433 addlongimgtag(base
, xsize
, ysize
);
435 verdat
= (unsigned char *)malloc(xsize
);
436 fseek(inf
, 512, SEEK_SET
);
437 for (z
= 0; z
< zsize
; z
++) {
440 lptr
+= (ysize
- 1) * xsize
442 for (y
= 0; y
< ysize
; y
++) {
443 fread(verdat
, xsize
, 1, inf
);
444 interleaverow(lptr
, verdat
, 3-z
, xsize
);
446 lptr
-= xsize
* sizeof(Py_UInt32
);
448 lptr
+= xsize
* sizeof(Py_UInt32
);
452 setalpha(base
, xsize
* ysize
);
454 copybw((Py_Int32
*) base
, xsize
* ysize
);
465 /* static utility functions for longimagedata */
468 interleaverow(lptr
, cptr
, z
, n
)
469 unsigned char *lptr
, *cptr
;
485 lptr
[0] = 0xff000000 + (0x010101 * (lptr
[0] & 0xff));
486 lptr
[1] = 0xff000000 + (0x010101 * (lptr
[1] & 0xff));
487 lptr
[2] = 0xff000000 + (0x010101 * (lptr
[2] & 0xff));
488 lptr
[3] = 0xff000000 + (0x010101 * (lptr
[3] & 0xff));
489 lptr
[4] = 0xff000000 + (0x010101 * (lptr
[4] & 0xff));
490 lptr
[5] = 0xff000000 + (0x010101 * (lptr
[5] & 0xff));
491 lptr
[6] = 0xff000000 + (0x010101 * (lptr
[6] & 0xff));
492 lptr
[7] = 0xff000000 + (0x010101 * (lptr
[7] & 0xff));
497 *lptr
= 0xff000000 + (0x010101 * (*lptr
&0xff));
525 expandrow(optr
, iptr
, z
)
526 unsigned char *optr
, *iptr
;
529 unsigned char pixel
, count
;
534 if (!(count
= (pixel
& 0x7f)))
538 optr
[0 * 4] = iptr
[0];
539 optr
[1 * 4] = iptr
[1];
540 optr
[2 * 4] = iptr
[2];
541 optr
[3 * 4] = iptr
[3];
542 optr
[4 * 4] = iptr
[4];
543 optr
[5 * 4] = iptr
[5];
544 optr
[6 * 4] = iptr
[6];
545 optr
[7 * 4] = iptr
[7];
579 * copy an array of longs to an iris image file. Each long
580 * represents one pixel. xsize and ysize specify the dimensions of
581 * the pixel array. zsize specifies what kind of image file to
582 * write out. if zsize is 1, the luminance of the pixels are
583 * calculated, and a sinlge channel black and white image is saved.
584 * If zsize is 3, an RGB image file is saved. If zsize is 4, an
585 * RGBA image file is saved.
589 longstoimage(self
, args
)
590 PyObject
*self
, *args
;
594 int xsize
, ysize
, zsize
;
597 int tablen
, y
, z
, pos
, len
;
598 Py_Int32
*starttab
= NULL
, *lengthtab
= NULL
;
599 unsigned char *rlebuf
= NULL
;
600 unsigned char *lumbuf
= NULL
;
601 int rlebuflen
, goodwrite
;
602 PyObject
*retval
= NULL
;
604 if (!PyArg_Parse(args
, "(s#iiis)", &lptr
, &len
, &xsize
, &ysize
, &zsize
,
609 outf
= fopen(name
, "wb");
611 PyErr_SetString(ImgfileError
, "can't open output file");
614 tablen
= ysize
* zsize
* sizeof(Py_Int32
);
616 starttab
= (Py_Int32
*)malloc(tablen
);
617 lengthtab
= (Py_Int32
*)malloc(tablen
);
618 rlebuflen
= (int) (1.05 * xsize
+ 10);
619 rlebuf
= (unsigned char *)malloc(rlebuflen
);
620 lumbuf
= (unsigned char *)malloc(xsize
* sizeof(Py_Int32
));
621 if (!starttab
|| !lengthtab
|| !rlebuf
|| !lumbuf
) {
626 memset(&image
, 0, sizeof(IMAGE
));
627 image
.imagic
= IMAGIC
;
638 goodwrite
*= writeheader(outf
, &image
);
639 pos
= 512 + 2 * tablen
;
640 fseek(outf
, pos
, SEEK_SET
);
642 lptr
+= (ysize
- 1) * xsize
* sizeof(Py_UInt32
);
643 for (y
= 0; y
< ysize
; y
++) {
644 for (z
= 0; z
< zsize
; z
++) {
646 lumrow(lptr
, lumbuf
, xsize
);
647 len
= compressrow(lumbuf
, rlebuf
,
648 CHANOFFSET(z
), xsize
);
650 len
= compressrow(lptr
, rlebuf
,
651 CHANOFFSET(z
), xsize
);
653 if(len
> rlebuflen
) {
654 PyErr_SetString(ImgfileError
,
655 "rlebuf is too small");
658 goodwrite
*= fwrite(rlebuf
, len
, 1, outf
);
659 starttab
[y
+ z
* ysize
] = pos
;
660 lengthtab
[y
+ z
* ysize
] = len
;
664 lptr
-= xsize
* sizeof(Py_UInt32
);
666 lptr
+= xsize
* sizeof(Py_UInt32
);
669 fseek(outf
, 512, SEEK_SET
);
670 goodwrite
*= writetab(outf
, starttab
, ysize
*zsize
);
671 goodwrite
*= writetab(outf
, lengthtab
, ysize
*zsize
);
676 PyErr_SetString(ImgfileError
, "not enough space for image");
687 /* static utility functions for longstoimage */
690 lumrow(rgbptr
, lumptr
, n
)
691 unsigned char *rgbptr
, *lumptr
;
694 lumptr
+= CHANOFFSET(0);
696 *lumptr
= ILUM(rgbptr
[OFFSET_R
],
705 compressrow(lbuf
, rlebuf
, z
, cnt
)
706 unsigned char *lbuf
, *rlebuf
;
709 unsigned char *iptr
, *ibufend
, *sptr
, *optr
;
715 ibufend
= iptr
+ cnt
* 4;
718 while(iptr
< ibufend
) {
721 while ((iptr
<ibufend
) &&
722 ((iptr
[-8]!=iptr
[-4]) ||(iptr
[-4]!=iptr
[0])))
727 count
= (iptr
- sptr
) / 4;
729 todo
= count
> 126 ? 126 : (short)count
;
731 *optr
++ = 0x80 | todo
;
733 optr
[0] = sptr
[0 * 4];
734 optr
[1] = sptr
[1 * 4];
735 optr
[2] = sptr
[2 * 4];
736 optr
[3] = sptr
[3 * 4];
737 optr
[4] = sptr
[4 * 4];
738 optr
[5] = sptr
[5 * 4];
739 optr
[6] = sptr
[6 * 4];
740 optr
[7] = sptr
[7 * 4];
753 while ((iptr
< ibufend
) && (*iptr
== cc
))
755 count
= (iptr
- sptr
) / 4;
757 todo
= count
> 126 ? 126 : (short)count
;
759 *optr
++ = (unsigned char) todo
;
760 *optr
++ = (unsigned char) cc
;
764 return optr
- (unsigned char *)rlebuf
;
774 if (!PyArg_Parse(args
, "i", &order
))
776 oldorder
= reverse_order
;
777 reverse_order
= order
;
778 return PyInt_FromLong(oldorder
);
783 {"sizeofimage", sizeofimage
},
784 {"longimagedata", longimagedata
},
785 {"longstoimage", longstoimage
},
787 {NULL
, NULL
} /* sentinel */
795 m
= Py_InitModule("rgbimg", rgbimg_methods
);
796 d
= PyModule_GetDict(m
);
797 ImgfileError
= PyErr_NewException("rgbimg.error", NULL
, NULL
);
798 if (ImgfileError
!= NULL
)
799 PyDict_SetItemString(d
, "error", ImgfileError
);