2 /* IMGFILE module - Interface to sgi libimage */
4 /* XXX This module should be done better at some point. It should return
5 ** an object of image file class, and have routines to manipulate these
6 ** image files in a neater way (so you can get rgb images off a greyscale
7 ** file, for instance, or do a straight display without having to get the
8 ** image bits into python, etc).
10 ** Warning: this module is very non-reentrant (esp. the readscaled stuff)
17 #include "/usr/people/4Dgifts/iristools/include/izoom.h"
19 /* Bunch of missing extern decls; keep gcc -Wall happy... */
20 extern void i_seterror();
22 extern void filterzoom();
26 static PyObject
* ImgfileError
; /* Exception we raise for various trouble */
28 static int top_to_bottom
; /* True if we want top-to-bottom images */
30 /* The image library does not always call the error hander :-(,
31 therefore we have a global variable indicating that it was called.
32 It is cleared by imgfile_open(). */
34 static int error_called
;
37 /* The error handler */
40 imgfile_error(char *str
)
42 PyErr_SetString(ImgfileError
, str
);
44 return; /* To imglib, which will return a failure indicator */
48 /* Open an image file and return a pointer to it.
49 Make sure we raise an exception if we fail. */
52 imgfile_open(char *fname
)
55 i_seterror(imgfile_error
);
58 if ( (image
= iopen(fname
, "r")) == NULL
) {
59 /* Error may already be set by imgfile_error */
60 if ( !error_called
) {
62 PyErr_SetFromErrno(ImgfileError
);
64 PyErr_SetString(ImgfileError
,
65 "Can't open image file");
73 imgfile_ttob(PyObject
*self
, PyObject
*args
)
78 if (!PyArg_ParseTuple(args
, "i:ttob", &newval
))
80 rv
= PyInt_FromLong(top_to_bottom
);
81 top_to_bottom
= newval
;
86 imgfile_read(PyObject
*self
, PyObject
*args
)
90 int xsize
, ysize
, zsize
;
93 static short rs
[8192], gs
[8192], bs
[8192];
96 int yfirst
, ylast
, ystep
;
98 if ( !PyArg_ParseTuple(args
, "s:read", &fname
) )
101 if ( (image
= imgfile_open(fname
)) == NULL
)
104 if ( image
->colormap
!= CM_NORMAL
) {
106 PyErr_SetString(ImgfileError
,
107 "Can only handle CM_NORMAL images");
110 if ( BPP(image
->type
) != 1 ) {
112 PyErr_SetString(ImgfileError
,
113 "Can't handle imgfiles with bpp!=1");
116 xsize
= image
->xsize
;
117 ysize
= image
->ysize
;
118 zsize
= image
->zsize
;
119 if ( zsize
!= 1 && zsize
!= 3) {
121 PyErr_SetString(ImgfileError
,
122 "Can only handle 1 or 3 byte pixels");
125 if ( xsize
> 8192 ) {
127 PyErr_SetString(ImgfileError
,
128 "Can't handle image with > 8192 columns");
132 if ( zsize
== 3 ) zsize
= 4;
133 rv
= PyString_FromStringAndSize((char *)NULL
, xsize
*ysize
*zsize
);
138 cdatap
= PyString_AsString(rv
);
139 idatap
= (long *)cdatap
;
150 for ( y
=yfirst
; y
!= ylast
&& !error_called
; y
+= ystep
) {
152 getrow(image
, rs
, y
, 0);
153 for(x
=0; x
<xsize
; x
++ )
156 getrow(image
, rs
, y
, 0);
157 getrow(image
, gs
, y
, 1);
158 getrow(image
, bs
, y
, 2);
159 for(x
=0; x
<xsize
; x
++ )
160 *idatap
++ = (rs
[x
] & 0xff) |
161 ((gs
[x
] & 0xff)<<8) |
162 ((bs
[x
] & 0xff)<<16);
166 if ( error_called
) {
173 static IMAGE
*glob_image
;
174 static long *glob_datap
;
175 static int glob_width
, glob_z
, glob_ysize
;
178 xs_get(short *buf
, int y
)
181 getrow(glob_image
, buf
, (glob_ysize
-1-y
), glob_z
);
183 getrow(glob_image
, buf
, y
, glob_z
);
187 xs_put_c(short *buf
, int y
)
189 char *datap
= (char *)glob_datap
+ y
*glob_width
;
190 int width
= glob_width
;
193 *datap
++ = (*buf
++) & 0xff;
197 xs_put_0(short *buf
, int y
)
199 long *datap
= glob_datap
+ y
*glob_width
;
200 int width
= glob_width
;
203 *datap
++ = (*buf
++) & 0xff;
206 xs_put_12(short *buf
, int y
)
208 long *datap
= glob_datap
+ y
*glob_width
;
209 int width
= glob_width
;
212 *datap
++ |= ((*buf
++) & 0xff) << (glob_z
*8);
216 xscale(IMAGE
*image
, int xsize
, int ysize
, int zsize
,
217 long *datap
, int xnew
, int ynew
, int fmode
, double blur
)
225 filterzoom(xs_get
, xs_put_c
, xsize
, ysize
,
226 xnew
, ynew
, fmode
, blur
);
229 filterzoom(xs_get
, xs_put_0
, xsize
, ysize
,
230 xnew
, ynew
, fmode
, blur
);
232 filterzoom(xs_get
, xs_put_12
, xsize
, ysize
,
233 xnew
, ynew
, fmode
, blur
);
235 filterzoom(xs_get
, xs_put_12
, xsize
, ysize
,
236 xnew
, ynew
, fmode
, blur
);
242 imgfile_readscaled(PyObject
*self
, PyObject
*args
)
246 int xsize
, ysize
, zsize
;
249 static short rs
[8192], gs
[8192], bs
[8192];
251 int xwtd
, ywtd
, xorig
, yorig
;
258 int yfirst
, ylast
, ystep
;
261 ** Parse args. Funny, since arg 4 and 5 are optional
262 ** (filter name and blur factor). Also, 4 or 5 arguments indicates
263 ** extended scale algorithm in stead of simple-minded pixel drop/dup.
265 extended
= PyTuple_Size(args
) >= 4;
266 if ( !PyArg_ParseTuple(args
, "sii|sd",
267 &fname
, &xwtd
, &ywtd
, &filter
, &blur
) )
271 ** Check parameters, open file and check type, rows, etc.
274 if ( strcmp(filter
, "impulse") == 0 )
276 else if ( strcmp( filter
, "box") == 0 )
278 else if ( strcmp( filter
, "triangle") == 0 )
280 else if ( strcmp( filter
, "quadratic") == 0 )
282 else if ( strcmp( filter
, "gaussian") == 0 )
285 PyErr_SetString(ImgfileError
, "Unknown filter type");
290 if ( (image
= imgfile_open(fname
)) == NULL
)
293 if ( image
->colormap
!= CM_NORMAL
) {
295 PyErr_SetString(ImgfileError
,
296 "Can only handle CM_NORMAL images");
299 if ( BPP(image
->type
) != 1 ) {
301 PyErr_SetString(ImgfileError
,
302 "Can't handle imgfiles with bpp!=1");
305 xsize
= image
->xsize
;
306 ysize
= image
->ysize
;
307 zsize
= image
->zsize
;
308 if ( zsize
!= 1 && zsize
!= 3) {
310 PyErr_SetString(ImgfileError
,
311 "Can only handle 1 or 3 byte pixels");
314 if ( xsize
> 8192 ) {
316 PyErr_SetString(ImgfileError
,
317 "Can't handle image with > 8192 columns");
321 if ( zsize
== 3 ) zsize
= 4;
322 rv
= PyString_FromStringAndSize(NULL
, xwtd
*ywtd
*zsize
);
327 PyFPE_START_PROTECT("readscaled", return 0)
328 xfac
= (float)xsize
/(float)xwtd
;
329 yfac
= (float)ysize
/(float)ywtd
;
330 PyFPE_END_PROTECT(yfac
)
331 cdatap
= PyString_AsString(rv
);
332 idatap
= (long *)cdatap
;
335 xscale(image
, xsize
, ysize
, zsize
,
336 idatap
, xwtd
, ywtd
, fmode
, blur
);
347 for ( y
=yfirst
; y
!= ylast
&& !error_called
; y
+= ystep
) {
348 yorig
= (int)(y
*yfac
);
350 getrow(image
, rs
, yorig
, 0);
351 for(x
=0; x
<xwtd
; x
++ ) {
352 *cdatap
++ = rs
[(int)(x
*xfac
)];
355 getrow(image
, rs
, yorig
, 0);
356 getrow(image
, gs
, yorig
, 1);
357 getrow(image
, bs
, yorig
, 2);
358 for(x
=0; x
<xwtd
; x
++ ) {
359 xorig
= (int)(x
*xfac
);
360 *idatap
++ = (rs
[xorig
] & 0xff) |
361 ((gs
[xorig
] & 0xff)<<8) |
362 ((bs
[xorig
] & 0xff)<<16);
368 if ( error_called
) {
376 imgfile_getsizes(PyObject
*self
, PyObject
*args
)
382 if ( !PyArg_ParseTuple(args
, "s:getsizes", &fname
) )
385 if ( (image
= imgfile_open(fname
)) == NULL
)
387 rv
= Py_BuildValue("(iii)", image
->xsize
, image
->ysize
, image
->zsize
);
393 imgfile_write(PyObject
*self
, PyObject
*args
)
397 int xsize
, ysize
, zsize
, len
;
400 short rs
[8192], gs
[8192], bs
[8192];
404 int yfirst
, ylast
, ystep
;
407 if ( !PyArg_ParseTuple(args
, "ss#iii:write",
408 &fname
, &cdatap
, &len
, &xsize
, &ysize
, &zsize
) )
411 if ( zsize
!= 1 && zsize
!= 3 ) {
412 PyErr_SetString(ImgfileError
,
413 "Can only handle 1 or 3 byte pixels");
416 if ( len
!= xsize
* ysize
* (zsize
== 1 ? 1 : 4) ) {
417 PyErr_SetString(ImgfileError
, "Data does not match sizes");
420 if ( xsize
> 8192 ) {
421 PyErr_SetString(ImgfileError
,
422 "Can't handle image with > 8192 columns");
428 image
=iopen(fname
, "w", RLE(1), 3, xsize
, ysize
, zsize
);
430 if ( ! error_called
) {
432 PyErr_SetFromErrno(ImgfileError
);
434 PyErr_SetString(ImgfileError
,
435 "Can't create image file");
440 idatap
= (long *)cdatap
;
451 for ( y
=yfirst
; y
!= ylast
&& !error_called
; y
+= ystep
) {
453 for( x
=0; x
<xsize
; x
++ )
455 putrow(image
, rs
, y
, 0);
457 for( x
=0; x
<xsize
; x
++ ) {
460 g
= (rgb
>> 8 ) & 0xff;
461 b
= (rgb
>> 16 ) & 0xff;
466 putrow(image
, rs
, y
, 0);
467 putrow(image
, gs
, y
, 1);
468 putrow(image
, bs
, y
, 2);
480 static PyMethodDef imgfile_methods
[] = {
481 { "getsizes", imgfile_getsizes
, METH_VARARGS
},
482 { "read", imgfile_read
, METH_VARARGS
},
483 { "readscaled", imgfile_readscaled
, METH_VARARGS
},
484 { "write", imgfile_write
, METH_VARARGS
},
485 { "ttob", imgfile_ttob
, METH_VARARGS
},
486 { NULL
, NULL
} /* Sentinel */
494 m
= Py_InitModule("imgfile", imgfile_methods
);
497 d
= PyModule_GetDict(m
);
498 ImgfileError
= PyErr_NewException("imgfile.error", NULL
, NULL
);
499 if (ImgfileError
!= NULL
)
500 PyDict_SetItemString(d
, "error", ImgfileError
);