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"
38 unsigned short imagic
; /* stuff saved on disk . . */
50 Py_Int32 file
; /* stuff used in core only */
59 unsigned short *tmpbuf
;
61 Py_UInt32 rleend
; /* for rle images */
62 Py_UInt32
*rowstart
; /* for rle images */
63 Py_Int32
*rowsize
; /* for rle images */
68 #define TYPEMASK 0xff00
69 #define BPPMASK 0x00ff
70 #define ITYPE_VERBATIM 0x0000
71 #define ITYPE_RLE 0x0100
72 #define ISRLE(type) (((type) & 0xff00) == ITYPE_RLE)
73 #define ISVERBATIM(type) (((type) & 0xff00) == ITYPE_VERBATIM)
74 #define BPP(type) ((type) & BPPMASK)
75 #define RLE(bpp) (ITYPE_RLE | (bpp))
76 #define VERBATIM(bpp) (ITYPE_VERBATIM | (bpp))
78 * end of image.h stuff
86 #define ILUM(r,g,b) ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8)
88 #define OFFSET_R 3 /* this is byte order dependent */
93 #define CHANOFFSET(z) (3-(z)) /* this is byte order dependent */
95 static void expandrow(unsigned char *, unsigned char *, int);
96 static void setalpha(unsigned char *, int);
97 static void copybw(Py_Int32
*, int);
98 static void interleaverow(unsigned char*, unsigned char*, int, int);
99 static int compressrow(unsigned char *, unsigned char *, int, int);
100 static void lumrow(unsigned char *, unsigned char *, int);
108 static PyObject
*ImgfileError
;
110 static int reverse_order
;
115 * this is used to extract image data from core dumps.
119 addlongimgtag(Py_UInt32
*dptr
, int xsize
, int ysize
)
121 dptr
= dptr
+ (xsize
* ysize
);
122 dptr
[0] = 0x12345678;
123 dptr
[1] = 0x59493333;
124 dptr
[2] = 0x69434222;
131 * byte order independent read/write of shorts and longs.
134 static unsigned short
137 unsigned char buf
[2];
139 fread(buf
, 2, 1, inf
);
140 return (buf
[0] << 8) + (buf
[1] << 0);
146 unsigned char buf
[4];
148 fread(buf
, 4, 1, inf
);
149 return (buf
[0] << 24) + (buf
[1] << 16) + (buf
[2] << 8) + (buf
[3] << 0);
153 putshort(FILE *outf
, unsigned short val
)
155 unsigned char buf
[2];
159 fwrite(buf
, 2, 1, outf
);
163 putlong(FILE *outf
, Py_UInt32 val
)
165 unsigned char buf
[4];
167 buf
[0] = (unsigned char) (val
>> 24);
168 buf
[1] = (unsigned char) (val
>> 16);
169 buf
[2] = (unsigned char) (val
>> 8);
170 buf
[3] = (unsigned char) (val
>> 0);
171 return (int)fwrite(buf
, 4, 1, outf
);
175 readheader(FILE *inf
, IMAGE
*image
)
177 memset(image
,0, sizeof(IMAGE
));
178 image
->imagic
= getshort(inf
);
179 image
->type
= getshort(inf
);
180 image
->dim
= getshort(inf
);
181 image
->xsize
= getshort(inf
);
182 image
->ysize
= getshort(inf
);
183 image
->zsize
= getshort(inf
);
187 writeheader(FILE *outf
, IMAGE
*image
)
191 memset(&t
, 0, sizeof(IMAGE
));
192 fwrite(&t
, sizeof(IMAGE
), 1, outf
);
193 fseek(outf
, 0, SEEK_SET
);
194 putshort(outf
, image
->imagic
);
195 putshort(outf
, image
->type
);
196 putshort(outf
, image
->dim
);
197 putshort(outf
, image
->xsize
);
198 putshort(outf
, image
->ysize
);
199 putshort(outf
, image
->zsize
);
200 putlong(outf
, image
->min
);
201 putlong(outf
, image
->max
);
203 return (int)fwrite("no name", 8, 1, outf
);
207 writetab(FILE *outf
, /*unsigned*/ Py_Int32
*tab
, int len
)
212 r
= putlong(outf
, *tab
++);
219 readtab(FILE *inf
, /*unsigned*/ Py_Int32
*tab
, int len
)
222 *tab
++ = getlong(inf
);
229 * return the xsize and ysize of an iris image file.
233 sizeofimage(PyObject
*self
, PyObject
*args
)
239 if (!PyArg_ParseTuple(args
, "s:sizeofimage", &name
))
242 inf
= fopen(name
, "rb");
244 PyErr_SetString(ImgfileError
, "can't open image file");
247 readheader(inf
, &image
);
249 if (image
.imagic
!= IMAGIC
) {
250 PyErr_SetString(ImgfileError
,
251 "bad magic number in image file");
254 return Py_BuildValue("(ii)", image
.xsize
, image
.ysize
);
259 * read in a B/W RGB or RGBA iris image file and return a
260 * pointer to an array of longs.
264 longimagedata(PyObject
*self
, PyObject
*args
)
267 unsigned char *base
, *lptr
;
268 unsigned char *rledat
= NULL
, *verdat
= NULL
;
269 Py_Int32
*starttab
= NULL
, *lengthtab
= NULL
;
273 int xsize
, ysize
, zsize
;
274 int bpp
, rle
, cur
, badorder
;
278 if (!PyArg_ParseTuple(args
, "s:longimagedata", &name
))
281 inf
= fopen(name
,"rb");
283 PyErr_SetString(ImgfileError
, "can't open image file");
286 readheader(inf
,&image
);
287 if (image
.imagic
!= IMAGIC
) {
288 PyErr_SetString(ImgfileError
,
289 "bad magic number in image file");
292 rle
= ISRLE(image
.type
);
293 bpp
= BPP(image
.type
);
295 PyErr_SetString(ImgfileError
,
296 "image must have 1 byte per pix chan");
303 tablen
= ysize
* zsize
* sizeof(Py_Int32
);
304 starttab
= (Py_Int32
*)malloc(tablen
);
305 lengthtab
= (Py_Int32
*)malloc(tablen
);
306 rlebuflen
= (int) (1.05 * xsize
+10);
307 rledat
= (unsigned char *)malloc(rlebuflen
);
308 if (!starttab
|| !lengthtab
|| !rledat
) {
313 fseek(inf
, 512, SEEK_SET
);
314 readtab(inf
, starttab
, ysize
*zsize
);
315 readtab(inf
, lengthtab
, ysize
*zsize
);
317 /* check data order */
320 for(y
= 0; y
< ysize
; y
++) {
321 for(z
= 0; z
< zsize
; z
++) {
322 if (starttab
[y
+ z
* ysize
] < cur
) {
326 cur
= starttab
[y
+z
* ysize
];
332 fseek(inf
, 512 + 2 * tablen
, SEEK_SET
);
333 cur
= 512 + 2 * tablen
;
334 rv
= PyString_FromStringAndSize((char *)NULL
,
335 (xsize
* ysize
+ TAGLEN
) * sizeof(Py_Int32
));
339 base
= (unsigned char *) PyString_AsString(rv
);
341 addlongimgtag(base
,xsize
,ysize
);
344 for (z
= 0; z
< zsize
; z
++) {
347 lptr
+= (ysize
- 1) * xsize
349 for (y
= 0; y
< ysize
; y
++) {
350 int idx
= y
+ z
* ysize
;
351 if (cur
!= starttab
[idx
]) {
352 fseek(inf
,starttab
[idx
],
356 if (lengthtab
[idx
] > rlebuflen
) {
357 PyErr_SetString(ImgfileError
,
358 "rlebuf is too small");
363 fread(rledat
, lengthtab
[idx
], 1, inf
);
364 cur
+= lengthtab
[idx
];
365 expandrow(lptr
, rledat
, 3-z
);
377 lptr
+= (ysize
- 1) * xsize
379 for (y
= 0; y
< ysize
; y
++) {
380 for(z
= 0; z
< zsize
; z
++) {
381 int idx
= y
+ z
* ysize
;
382 if (cur
!= starttab
[idx
]) {
383 fseek(inf
, starttab
[idx
],
387 fread(rledat
, lengthtab
[idx
], 1, inf
);
388 cur
+= lengthtab
[idx
];
389 expandrow(lptr
, rledat
, 3-z
);
392 lptr
-= xsize
* sizeof(Py_UInt32
);
394 lptr
+= xsize
* sizeof(Py_UInt32
);
398 setalpha(base
, xsize
* ysize
);
400 copybw((Py_Int32
*) base
, xsize
* ysize
);
403 rv
= PyString_FromStringAndSize((char *) 0,
404 (xsize
*ysize
+TAGLEN
)*sizeof(Py_Int32
));
408 base
= (unsigned char *) PyString_AsString(rv
);
410 addlongimgtag(base
, xsize
, ysize
);
412 verdat
= (unsigned char *)malloc(xsize
);
418 fseek(inf
, 512, SEEK_SET
);
419 for (z
= 0; z
< zsize
; z
++) {
422 lptr
+= (ysize
- 1) * xsize
424 for (y
= 0; y
< ysize
; y
++) {
425 fread(verdat
, xsize
, 1, inf
);
426 interleaverow(lptr
, verdat
, 3-z
, xsize
);
428 lptr
-= xsize
* sizeof(Py_UInt32
);
430 lptr
+= xsize
* sizeof(Py_UInt32
);
434 setalpha(base
, xsize
* ysize
);
436 copybw((Py_Int32
*) base
, xsize
* ysize
);
451 /* static utility functions for longimagedata */
454 interleaverow(unsigned char *lptr
, unsigned char *cptr
, int z
, int n
)
464 copybw(Py_Int32
*lptr
, int n
)
467 lptr
[0] = 0xff000000 + (0x010101 * (lptr
[0] & 0xff));
468 lptr
[1] = 0xff000000 + (0x010101 * (lptr
[1] & 0xff));
469 lptr
[2] = 0xff000000 + (0x010101 * (lptr
[2] & 0xff));
470 lptr
[3] = 0xff000000 + (0x010101 * (lptr
[3] & 0xff));
471 lptr
[4] = 0xff000000 + (0x010101 * (lptr
[4] & 0xff));
472 lptr
[5] = 0xff000000 + (0x010101 * (lptr
[5] & 0xff));
473 lptr
[6] = 0xff000000 + (0x010101 * (lptr
[6] & 0xff));
474 lptr
[7] = 0xff000000 + (0x010101 * (lptr
[7] & 0xff));
479 *lptr
= 0xff000000 + (0x010101 * (*lptr
&0xff));
485 setalpha(unsigned char *lptr
, int n
)
506 expandrow(unsigned char *optr
, unsigned char *iptr
, int z
)
508 unsigned char pixel
, count
;
513 if (!(count
= (pixel
& 0x7f)))
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];
558 * copy an array of longs to an iris image file. Each long
559 * represents one pixel. xsize and ysize specify the dimensions of
560 * the pixel array. zsize specifies what kind of image file to
561 * write out. if zsize is 1, the luminance of the pixels are
562 * calculated, and a single channel black and white image is saved.
563 * If zsize is 3, an RGB image file is saved. If zsize is 4, an
564 * RGBA image file is saved.
568 longstoimage(PyObject
*self
, PyObject
*args
)
572 int xsize
, ysize
, zsize
;
575 int tablen
, y
, z
, pos
, len
;
576 Py_Int32
*starttab
= NULL
, *lengthtab
= NULL
;
577 unsigned char *rlebuf
= NULL
;
578 unsigned char *lumbuf
= NULL
;
580 Py_ssize_t goodwrite
;
581 PyObject
*retval
= NULL
;
583 if (!PyArg_ParseTuple(args
, "s#iiis:longstoimage", &lptr
, &len
,
584 &xsize
, &ysize
, &zsize
, &name
))
588 outf
= fopen(name
, "wb");
590 PyErr_SetString(ImgfileError
, "can't open output file");
593 tablen
= ysize
* zsize
* sizeof(Py_Int32
);
595 starttab
= (Py_Int32
*)malloc(tablen
);
596 lengthtab
= (Py_Int32
*)malloc(tablen
);
597 rlebuflen
= (int) (1.05 * xsize
+ 10);
598 rlebuf
= (unsigned char *)malloc(rlebuflen
);
599 lumbuf
= (unsigned char *)malloc(xsize
* sizeof(Py_Int32
));
600 if (!starttab
|| !lengthtab
|| !rlebuf
|| !lumbuf
) {
605 memset(&image
, 0, sizeof(IMAGE
));
606 image
.imagic
= IMAGIC
;
617 goodwrite
*= writeheader(outf
, &image
);
618 pos
= 512 + 2 * tablen
;
619 fseek(outf
, pos
, SEEK_SET
);
621 lptr
+= (ysize
- 1) * xsize
* sizeof(Py_UInt32
);
622 for (y
= 0; y
< ysize
; y
++) {
623 for (z
= 0; z
< zsize
; z
++) {
625 lumrow(lptr
, lumbuf
, xsize
);
626 len
= compressrow(lumbuf
, rlebuf
,
627 CHANOFFSET(z
), xsize
);
629 len
= compressrow(lptr
, rlebuf
,
630 CHANOFFSET(z
), xsize
);
632 if(len
> rlebuflen
) {
633 PyErr_SetString(ImgfileError
,
634 "rlebuf is too small");
637 goodwrite
*= fwrite(rlebuf
, len
, 1, outf
);
638 starttab
[y
+ z
* ysize
] = pos
;
639 lengthtab
[y
+ z
* ysize
] = len
;
643 lptr
-= xsize
* sizeof(Py_UInt32
);
645 lptr
+= xsize
* sizeof(Py_UInt32
);
648 fseek(outf
, 512, SEEK_SET
);
649 goodwrite
*= writetab(outf
, starttab
, ysize
*zsize
);
650 goodwrite
*= writetab(outf
, lengthtab
, ysize
*zsize
);
655 PyErr_SetString(ImgfileError
, "not enough space for image");
666 /* static utility functions for longstoimage */
669 lumrow(unsigned char *rgbptr
, unsigned char *lumptr
, int n
)
671 lumptr
+= CHANOFFSET(0);
673 *lumptr
= ILUM(rgbptr
[OFFSET_R
],
682 compressrow(unsigned char *lbuf
, unsigned char *rlebuf
, int z
, int cnt
)
684 unsigned char *iptr
, *ibufend
, *sptr
, *optr
;
690 ibufend
= iptr
+ cnt
* 4;
693 while(iptr
< ibufend
) {
696 while ((iptr
<ibufend
) &&
697 ((iptr
[-8]!=iptr
[-4]) ||(iptr
[-4]!=iptr
[0])))
702 count
= (iptr
- sptr
) / 4;
704 todo
= count
> 126 ? 126 : (short)count
;
706 *optr
++ = 0x80 | todo
;
708 optr
[0] = sptr
[0 * 4];
709 optr
[1] = sptr
[1 * 4];
710 optr
[2] = sptr
[2 * 4];
711 optr
[3] = sptr
[3 * 4];
712 optr
[4] = sptr
[4 * 4];
713 optr
[5] = sptr
[5 * 4];
714 optr
[6] = sptr
[6 * 4];
715 optr
[7] = sptr
[7 * 4];
728 while ((iptr
< ibufend
) && (*iptr
== cc
))
730 count
= (iptr
- sptr
) / 4;
732 todo
= count
> 126 ? 126 : (short)count
;
734 *optr
++ = (unsigned char) todo
;
735 *optr
++ = (unsigned char) cc
;
739 return optr
- (unsigned char *)rlebuf
;
743 ttob(PyObject
*self
, PyObject
*args
)
747 if (!PyArg_ParseTuple(args
, "i:ttob", &order
))
749 oldorder
= reverse_order
;
750 reverse_order
= order
;
751 return PyInt_FromLong(oldorder
);
756 {"sizeofimage", sizeofimage
, METH_VARARGS
},
757 {"longimagedata", longimagedata
, METH_VARARGS
},
758 {"longstoimage", longstoimage
, METH_VARARGS
},
759 {"ttob", ttob
, METH_VARARGS
},
760 {NULL
, NULL
} /* sentinel */
768 m
= Py_InitModule("rgbimg", rgbimg_methods
);
772 if (PyErr_Warn(PyExc_DeprecationWarning
,
773 "the rgbimg module is deprecated"))
776 d
= PyModule_GetDict(m
);
777 ImgfileError
= PyErr_NewException("rgbimg.error", NULL
, NULL
);
778 if (ImgfileError
!= NULL
)
779 PyDict_SetItemString(d
, "error", ImgfileError
);