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(unsigned char *, unsigned char *, int);
99 static void setalpha(unsigned char *, int);
100 static void copybw(Py_Int32
*, int);
101 static void interleaverow(unsigned char*, unsigned char*, int, int);
102 static int compressrow(unsigned char *, unsigned char *, int, int);
103 static void lumrow(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(Py_UInt32
*dptr
, int xsize
, int ysize
)
124 dptr
= dptr
+ (xsize
* ysize
);
125 dptr
[0] = 0x12345678;
126 dptr
[1] = 0x59493333;
127 dptr
[2] = 0x69434222;
134 * byte order independent read/write of shorts and longs.
137 static unsigned short
140 unsigned char buf
[2];
142 fread(buf
, 2, 1, inf
);
143 return (buf
[0] << 8) + (buf
[1] << 0);
149 unsigned char buf
[4];
151 fread(buf
, 4, 1, inf
);
152 return (buf
[0] << 24) + (buf
[1] << 16) + (buf
[2] << 8) + (buf
[3] << 0);
156 putshort(FILE *outf
, unsigned short val
)
158 unsigned char buf
[2];
162 fwrite(buf
, 2, 1, outf
);
166 putlong(FILE *outf
, Py_UInt32 val
)
168 unsigned char buf
[4];
170 buf
[0] = (unsigned char) (val
>> 24);
171 buf
[1] = (unsigned char) (val
>> 16);
172 buf
[2] = (unsigned char) (val
>> 8);
173 buf
[3] = (unsigned char) (val
>> 0);
174 return fwrite(buf
, 4, 1, outf
);
178 readheader(FILE *inf
, IMAGE
*image
)
180 memset(image
,0, sizeof(IMAGE
));
181 image
->imagic
= getshort(inf
);
182 image
->type
= getshort(inf
);
183 image
->dim
= getshort(inf
);
184 image
->xsize
= getshort(inf
);
185 image
->ysize
= getshort(inf
);
186 image
->zsize
= getshort(inf
);
190 writeheader(FILE *outf
, IMAGE
*image
)
194 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
);
206 return fwrite("no name", 8, 1, outf
);
210 writetab(FILE *outf
, /*unsigned*/ Py_Int32
*tab
, int len
)
215 r
= putlong(outf
, *tab
++);
222 readtab(FILE *inf
, /*unsigned*/ Py_Int32
*tab
, int len
)
225 *tab
++ = getlong(inf
);
232 * return the xsize and ysize of an iris image file.
236 sizeofimage(PyObject
*self
, PyObject
*args
)
242 if (!PyArg_Parse(args
, "s", &name
))
245 inf
= fopen(name
, "rb");
247 PyErr_SetString(ImgfileError
, "can't open image file");
250 readheader(inf
, &image
);
252 if (image
.imagic
!= IMAGIC
) {
253 PyErr_SetString(ImgfileError
,
254 "bad magic number in image file");
257 return Py_BuildValue("(ii)", image
.xsize
, image
.ysize
);
262 * read in a B/W RGB or RGBA iris image file and return a
263 * pointer to an array of longs.
267 longimagedata(PyObject
*self
, PyObject
*args
)
270 unsigned char *base
, *lptr
;
271 unsigned char *rledat
= NULL
, *verdat
= NULL
;
272 Py_Int32
*starttab
= NULL
, *lengthtab
= NULL
;
276 int xsize
, ysize
, zsize
;
277 int bpp
, rle
, cur
, badorder
;
281 if (!PyArg_Parse(args
, "s", &name
))
284 inf
= fopen(name
,"rb");
286 PyErr_SetString(ImgfileError
, "can't open image file");
289 readheader(inf
,&image
);
290 if (image
.imagic
!= IMAGIC
) {
291 PyErr_SetString(ImgfileError
,
292 "bad magic number in image file");
295 rle
= ISRLE(image
.type
);
296 bpp
= BPP(image
.type
);
298 PyErr_SetString(ImgfileError
,
299 "image must have 1 byte per pix chan");
306 tablen
= ysize
* zsize
* sizeof(Py_Int32
);
307 starttab
= (Py_Int32
*)malloc(tablen
);
308 lengthtab
= (Py_Int32
*)malloc(tablen
);
309 rlebuflen
= (int) (1.05 * xsize
+10);
310 rledat
= (unsigned char *)malloc(rlebuflen
);
311 if (!starttab
|| !lengthtab
|| !rledat
) {
316 fseek(inf
, 512, SEEK_SET
);
317 readtab(inf
, starttab
, ysize
*zsize
);
318 readtab(inf
, lengthtab
, ysize
*zsize
);
320 /* check data order */
323 for(y
= 0; y
< ysize
; y
++) {
324 for(z
= 0; z
< zsize
; z
++) {
325 if (starttab
[y
+ z
* ysize
] < cur
) {
329 cur
= starttab
[y
+z
* ysize
];
335 fseek(inf
, 512 + 2 * tablen
, SEEK_SET
);
336 cur
= 512 + 2 * tablen
;
337 rv
= PyString_FromStringAndSize((char *)NULL
,
338 (xsize
* ysize
+ TAGLEN
) * sizeof(Py_Int32
));
342 base
= (unsigned char *) PyString_AsString(rv
);
344 addlongimgtag(base
,xsize
,ysize
);
347 for (z
= 0; z
< zsize
; z
++) {
350 lptr
+= (ysize
- 1) * xsize
352 for (y
= 0; y
< ysize
; y
++) {
353 int idx
= y
+ z
* ysize
;
354 if (cur
!= starttab
[idx
]) {
355 fseek(inf
,starttab
[idx
],
359 if (lengthtab
[idx
] > rlebuflen
) {
360 PyErr_SetString(ImgfileError
,
361 "rlebuf is too small");
366 fread(rledat
, lengthtab
[idx
], 1, inf
);
367 cur
+= lengthtab
[idx
];
368 expandrow(lptr
, rledat
, 3-z
);
380 lptr
+= (ysize
- 1) * xsize
382 for (y
= 0; y
< ysize
; y
++) {
383 for(z
= 0; z
< zsize
; z
++) {
384 int idx
= y
+ z
* ysize
;
385 if (cur
!= starttab
[idx
]) {
386 fseek(inf
, starttab
[idx
],
390 fread(rledat
, lengthtab
[idx
], 1, inf
);
391 cur
+= lengthtab
[idx
];
392 expandrow(lptr
, rledat
, 3-z
);
395 lptr
-= xsize
* sizeof(Py_UInt32
);
397 lptr
+= xsize
* sizeof(Py_UInt32
);
401 setalpha(base
, xsize
* ysize
);
403 copybw((Py_Int32
*) base
, xsize
* ysize
);
406 rv
= PyString_FromStringAndSize((char *) 0,
407 (xsize
*ysize
+TAGLEN
)*sizeof(Py_Int32
));
411 base
= (unsigned char *) PyString_AsString(rv
);
413 addlongimgtag(base
, xsize
, ysize
);
415 verdat
= (unsigned char *)malloc(xsize
);
416 fseek(inf
, 512, SEEK_SET
);
417 for (z
= 0; z
< zsize
; z
++) {
420 lptr
+= (ysize
- 1) * xsize
422 for (y
= 0; y
< ysize
; y
++) {
423 fread(verdat
, xsize
, 1, inf
);
424 interleaverow(lptr
, verdat
, 3-z
, xsize
);
426 lptr
-= xsize
* sizeof(Py_UInt32
);
428 lptr
+= xsize
* sizeof(Py_UInt32
);
432 setalpha(base
, xsize
* ysize
);
434 copybw((Py_Int32
*) base
, xsize
* ysize
);
445 /* static utility functions for longimagedata */
448 interleaverow(unsigned char *lptr
, unsigned char *cptr
, int z
, int n
)
458 copybw(Py_Int32
*lptr
, int n
)
461 lptr
[0] = 0xff000000 + (0x010101 * (lptr
[0] & 0xff));
462 lptr
[1] = 0xff000000 + (0x010101 * (lptr
[1] & 0xff));
463 lptr
[2] = 0xff000000 + (0x010101 * (lptr
[2] & 0xff));
464 lptr
[3] = 0xff000000 + (0x010101 * (lptr
[3] & 0xff));
465 lptr
[4] = 0xff000000 + (0x010101 * (lptr
[4] & 0xff));
466 lptr
[5] = 0xff000000 + (0x010101 * (lptr
[5] & 0xff));
467 lptr
[6] = 0xff000000 + (0x010101 * (lptr
[6] & 0xff));
468 lptr
[7] = 0xff000000 + (0x010101 * (lptr
[7] & 0xff));
473 *lptr
= 0xff000000 + (0x010101 * (*lptr
&0xff));
479 setalpha(unsigned char *lptr
, int n
)
500 expandrow(unsigned char *optr
, unsigned char *iptr
, int z
)
502 unsigned char pixel
, count
;
507 if (!(count
= (pixel
& 0x7f)))
511 optr
[0 * 4] = iptr
[0];
512 optr
[1 * 4] = iptr
[1];
513 optr
[2 * 4] = iptr
[2];
514 optr
[3 * 4] = iptr
[3];
515 optr
[4 * 4] = iptr
[4];
516 optr
[5 * 4] = iptr
[5];
517 optr
[6 * 4] = iptr
[6];
518 optr
[7 * 4] = iptr
[7];
552 * copy an array of longs to an iris image file. Each long
553 * represents one pixel. xsize and ysize specify the dimensions of
554 * the pixel array. zsize specifies what kind of image file to
555 * write out. if zsize is 1, the luminance of the pixels are
556 * calculated, and a single channel black and white image is saved.
557 * If zsize is 3, an RGB image file is saved. If zsize is 4, an
558 * RGBA image file is saved.
562 longstoimage(PyObject
*self
, PyObject
*args
)
566 int xsize
, ysize
, zsize
;
569 int tablen
, y
, z
, pos
, len
;
570 Py_Int32
*starttab
= NULL
, *lengthtab
= NULL
;
571 unsigned char *rlebuf
= NULL
;
572 unsigned char *lumbuf
= NULL
;
573 int rlebuflen
, goodwrite
;
574 PyObject
*retval
= NULL
;
576 if (!PyArg_Parse(args
, "(s#iiis)", &lptr
, &len
, &xsize
, &ysize
, &zsize
,
581 outf
= fopen(name
, "wb");
583 PyErr_SetString(ImgfileError
, "can't open output file");
586 tablen
= ysize
* zsize
* sizeof(Py_Int32
);
588 starttab
= (Py_Int32
*)malloc(tablen
);
589 lengthtab
= (Py_Int32
*)malloc(tablen
);
590 rlebuflen
= (int) (1.05 * xsize
+ 10);
591 rlebuf
= (unsigned char *)malloc(rlebuflen
);
592 lumbuf
= (unsigned char *)malloc(xsize
* sizeof(Py_Int32
));
593 if (!starttab
|| !lengthtab
|| !rlebuf
|| !lumbuf
) {
598 memset(&image
, 0, sizeof(IMAGE
));
599 image
.imagic
= IMAGIC
;
610 goodwrite
*= writeheader(outf
, &image
);
611 pos
= 512 + 2 * tablen
;
612 fseek(outf
, pos
, SEEK_SET
);
614 lptr
+= (ysize
- 1) * xsize
* sizeof(Py_UInt32
);
615 for (y
= 0; y
< ysize
; y
++) {
616 for (z
= 0; z
< zsize
; z
++) {
618 lumrow(lptr
, lumbuf
, xsize
);
619 len
= compressrow(lumbuf
, rlebuf
,
620 CHANOFFSET(z
), xsize
);
622 len
= compressrow(lptr
, rlebuf
,
623 CHANOFFSET(z
), xsize
);
625 if(len
> rlebuflen
) {
626 PyErr_SetString(ImgfileError
,
627 "rlebuf is too small");
630 goodwrite
*= fwrite(rlebuf
, len
, 1, outf
);
631 starttab
[y
+ z
* ysize
] = pos
;
632 lengthtab
[y
+ z
* ysize
] = len
;
636 lptr
-= xsize
* sizeof(Py_UInt32
);
638 lptr
+= xsize
* sizeof(Py_UInt32
);
641 fseek(outf
, 512, SEEK_SET
);
642 goodwrite
*= writetab(outf
, starttab
, ysize
*zsize
);
643 goodwrite
*= writetab(outf
, lengthtab
, ysize
*zsize
);
648 PyErr_SetString(ImgfileError
, "not enough space for image");
659 /* static utility functions for longstoimage */
662 lumrow(unsigned char *rgbptr
, unsigned char *lumptr
, int n
)
664 lumptr
+= CHANOFFSET(0);
666 *lumptr
= ILUM(rgbptr
[OFFSET_R
],
675 compressrow(unsigned char *lbuf
, unsigned char *rlebuf
, int z
, int cnt
)
677 unsigned char *iptr
, *ibufend
, *sptr
, *optr
;
683 ibufend
= iptr
+ cnt
* 4;
686 while(iptr
< ibufend
) {
689 while ((iptr
<ibufend
) &&
690 ((iptr
[-8]!=iptr
[-4]) ||(iptr
[-4]!=iptr
[0])))
695 count
= (iptr
- sptr
) / 4;
697 todo
= count
> 126 ? 126 : (short)count
;
699 *optr
++ = 0x80 | todo
;
701 optr
[0] = sptr
[0 * 4];
702 optr
[1] = sptr
[1 * 4];
703 optr
[2] = sptr
[2 * 4];
704 optr
[3] = sptr
[3 * 4];
705 optr
[4] = sptr
[4 * 4];
706 optr
[5] = sptr
[5 * 4];
707 optr
[6] = sptr
[6 * 4];
708 optr
[7] = sptr
[7 * 4];
721 while ((iptr
< ibufend
) && (*iptr
== cc
))
723 count
= (iptr
- sptr
) / 4;
725 todo
= count
> 126 ? 126 : (short)count
;
727 *optr
++ = (unsigned char) todo
;
728 *optr
++ = (unsigned char) cc
;
732 return optr
- (unsigned char *)rlebuf
;
736 ttob(PyObject
*self
, PyObject
*args
)
740 if (!PyArg_Parse(args
, "i", &order
))
742 oldorder
= reverse_order
;
743 reverse_order
= order
;
744 return PyInt_FromLong(oldorder
);
749 {"sizeofimage", sizeofimage
},
750 {"longimagedata", longimagedata
},
751 {"longstoimage", longstoimage
},
753 {NULL
, NULL
} /* sentinel */
761 m
= Py_InitModule("rgbimg", rgbimg_methods
);
762 d
= PyModule_GetDict(m
);
763 ImgfileError
= PyErr_NewException("rgbimg.error", NULL
, NULL
);
764 if (ImgfileError
!= NULL
)
765 PyDict_SetItemString(d
, "error", ImgfileError
);