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_Parse(args
, "i", &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_Parse(args
, "s", &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
;
259 int yfirst
, ylast
, ystep
;
262 ** Parse args. Funny, since arg 4 and 5 are optional
263 ** (filter name and blur factor). Also, 4 or 5 arguments indicates
264 ** extended scale algorithm in stead of simple-minded pixel drop/dup.
267 cnt
= PyTuple_Size(args
);
270 if ( !PyArg_Parse(args
, "(siisd)",
271 &fname
, &xwtd
, &ywtd
, &filter
, &blur
) )
273 } else if ( cnt
== 4 ) {
275 if ( !PyArg_Parse(args
, "(siis)",
276 &fname
, &xwtd
, &ywtd
, &filter
) )
279 } else if ( !PyArg_Parse(args
, "(sii)", &fname
, &xwtd
, &ywtd
) )
283 ** Check parameters, open file and check type, rows, etc.
286 if ( strcmp(filter
, "impulse") == 0 )
288 else if ( strcmp( filter
, "box") == 0 )
290 else if ( strcmp( filter
, "triangle") == 0 )
292 else if ( strcmp( filter
, "quadratic") == 0 )
294 else if ( strcmp( filter
, "gaussian") == 0 )
297 PyErr_SetString(ImgfileError
, "Unknown filter type");
302 if ( (image
= imgfile_open(fname
)) == NULL
)
305 if ( image
->colormap
!= CM_NORMAL
) {
307 PyErr_SetString(ImgfileError
,
308 "Can only handle CM_NORMAL images");
311 if ( BPP(image
->type
) != 1 ) {
313 PyErr_SetString(ImgfileError
,
314 "Can't handle imgfiles with bpp!=1");
317 xsize
= image
->xsize
;
318 ysize
= image
->ysize
;
319 zsize
= image
->zsize
;
320 if ( zsize
!= 1 && zsize
!= 3) {
322 PyErr_SetString(ImgfileError
,
323 "Can only handle 1 or 3 byte pixels");
326 if ( xsize
> 8192 ) {
328 PyErr_SetString(ImgfileError
,
329 "Can't handle image with > 8192 columns");
333 if ( zsize
== 3 ) zsize
= 4;
334 rv
= PyString_FromStringAndSize(NULL
, xwtd
*ywtd
*zsize
);
339 PyFPE_START_PROTECT("readscaled", return 0)
340 xfac
= (float)xsize
/(float)xwtd
;
341 yfac
= (float)ysize
/(float)ywtd
;
342 PyFPE_END_PROTECT(yfac
)
343 cdatap
= PyString_AsString(rv
);
344 idatap
= (long *)cdatap
;
347 xscale(image
, xsize
, ysize
, zsize
,
348 idatap
, xwtd
, ywtd
, fmode
, blur
);
359 for ( y
=yfirst
; y
!= ylast
&& !error_called
; y
+= ystep
) {
360 yorig
= (int)(y
*yfac
);
362 getrow(image
, rs
, yorig
, 0);
363 for(x
=0; x
<xwtd
; x
++ ) {
364 *cdatap
++ = rs
[(int)(x
*xfac
)];
367 getrow(image
, rs
, yorig
, 0);
368 getrow(image
, gs
, yorig
, 1);
369 getrow(image
, bs
, yorig
, 2);
370 for(x
=0; x
<xwtd
; x
++ ) {
371 xorig
= (int)(x
*xfac
);
372 *idatap
++ = (rs
[xorig
] & 0xff) |
373 ((gs
[xorig
] & 0xff)<<8) |
374 ((bs
[xorig
] & 0xff)<<16);
380 if ( error_called
) {
388 imgfile_getsizes(PyObject
*self
, PyObject
*args
)
394 if ( !PyArg_Parse(args
, "s", &fname
) )
397 if ( (image
= imgfile_open(fname
)) == NULL
)
399 rv
= Py_BuildValue("(iii)", image
->xsize
, image
->ysize
, image
->zsize
);
405 imgfile_write(PyObject
*self
, PyObject
*args
)
409 int xsize
, ysize
, zsize
, len
;
412 short rs
[8192], gs
[8192], bs
[8192];
416 int yfirst
, ylast
, ystep
;
419 if ( !PyArg_Parse(args
, "(ss#iii)",
420 &fname
, &cdatap
, &len
, &xsize
, &ysize
, &zsize
) )
423 if ( zsize
!= 1 && zsize
!= 3 ) {
424 PyErr_SetString(ImgfileError
,
425 "Can only handle 1 or 3 byte pixels");
428 if ( len
!= xsize
* ysize
* (zsize
== 1 ? 1 : 4) ) {
429 PyErr_SetString(ImgfileError
, "Data does not match sizes");
432 if ( xsize
> 8192 ) {
433 PyErr_SetString(ImgfileError
,
434 "Can't handle image with > 8192 columns");
440 image
=iopen(fname
, "w", RLE(1), 3, xsize
, ysize
, zsize
);
442 if ( ! error_called
) {
444 PyErr_SetFromErrno(ImgfileError
);
446 PyErr_SetString(ImgfileError
,
447 "Can't create image file");
452 idatap
= (long *)cdatap
;
463 for ( y
=yfirst
; y
!= ylast
&& !error_called
; y
+= ystep
) {
465 for( x
=0; x
<xsize
; x
++ )
467 putrow(image
, rs
, y
, 0);
469 for( x
=0; x
<xsize
; x
++ ) {
472 g
= (rgb
>> 8 ) & 0xff;
473 b
= (rgb
>> 16 ) & 0xff;
478 putrow(image
, rs
, y
, 0);
479 putrow(image
, gs
, y
, 1);
480 putrow(image
, bs
, y
, 2);
492 static PyMethodDef imgfile_methods
[] = {
493 { "getsizes", imgfile_getsizes
},
494 { "read", imgfile_read
},
495 { "readscaled", imgfile_readscaled
, 1},
496 { "write", imgfile_write
},
497 { "ttob", imgfile_ttob
},
498 { NULL
, NULL
} /* Sentinel */
506 m
= Py_InitModule("imgfile", imgfile_methods
);
507 d
= PyModule_GetDict(m
);
508 ImgfileError
= PyErr_NewException("imgfile.error", NULL
, NULL
);
509 if (ImgfileError
!= NULL
)
510 PyDict_SetItemString(d
, "error", ImgfileError
);