1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* IMGFILE module - Interface to sgi libimage */
34 /* XXX This modele should be done better at some point. It should return
35 ** an object of image file class, and have routines to manipulate these
36 ** image files in a neater way (so you can get rgb images off a greyscale
37 ** file, for instance, or do a straight display without having to get the
38 ** image bits into python, etc).
40 ** Warning: this module is very non-reentrant (esp. the readscaled stuff)
47 #include "/usr/people/4Dgifts/iristools/include/izoom.h"
49 /* Bunch of missing extern decls; keep gcc -Wall happy... */
50 extern void i_seterror();
52 extern void filterzoom();
56 static PyObject
* ImgfileError
; /* Exception we raise for various trouble */
58 static int top_to_bottom
; /* True if we want top-to-bottom images */
60 /* The image library does not always call the error hander :-(,
61 therefore we have a global variable indicating that it was called.
62 It is cleared by imgfile_open(). */
64 static int error_called
;
67 /* The error handler */
73 PyErr_SetString(ImgfileError
, str
);
75 return; /* To imglib, which will return a failure indicator */
79 /* Open an image file and return a pointer to it.
80 Make sure we raise an exception if we fail. */
87 i_seterror(imgfile_error
);
90 if ( (image
= iopen(fname
, "r")) == NULL
) {
91 /* Error may already be set by imgfile_error */
92 if ( !error_called
) {
94 PyErr_SetFromErrno(ImgfileError
);
96 PyErr_SetString(ImgfileError
,
97 "Can't open image file");
105 imgfile_ttob(self
, args
)
112 if (!PyArg_Parse(args
, "i", &newval
))
114 rv
= PyInt_FromLong(top_to_bottom
);
115 top_to_bottom
= newval
;
120 imgfile_read(self
, args
)
126 int xsize
, ysize
, zsize
;
129 static short rs
[8192], gs
[8192], bs
[8192];
132 int yfirst
, ylast
, ystep
;
134 if ( !PyArg_Parse(args
, "s", &fname
) )
137 if ( (image
= imgfile_open(fname
)) == NULL
)
140 if ( image
->colormap
!= CM_NORMAL
) {
142 PyErr_SetString(ImgfileError
,
143 "Can only handle CM_NORMAL images");
146 if ( BPP(image
->type
) != 1 ) {
148 PyErr_SetString(ImgfileError
,
149 "Can't handle imgfiles with bpp!=1");
152 xsize
= image
->xsize
;
153 ysize
= image
->ysize
;
154 zsize
= image
->zsize
;
155 if ( zsize
!= 1 && zsize
!= 3) {
157 PyErr_SetString(ImgfileError
,
158 "Can only handle 1 or 3 byte pixels");
161 if ( xsize
> 8192 ) {
163 PyErr_SetString(ImgfileError
,
164 "Can't handle image with > 8192 columns");
168 if ( zsize
== 3 ) zsize
= 4;
169 rv
= PyString_FromStringAndSize((char *)NULL
, xsize
*ysize
*zsize
);
174 cdatap
= PyString_AsString(rv
);
175 idatap
= (long *)cdatap
;
186 for ( y
=yfirst
; y
!= ylast
&& !error_called
; y
+= ystep
) {
188 getrow(image
, rs
, y
, 0);
189 for(x
=0; x
<xsize
; x
++ )
192 getrow(image
, rs
, y
, 0);
193 getrow(image
, gs
, y
, 1);
194 getrow(image
, bs
, y
, 2);
195 for(x
=0; x
<xsize
; x
++ )
196 *idatap
++ = (rs
[x
] & 0xff) |
197 ((gs
[x
] & 0xff)<<8) |
198 ((bs
[x
] & 0xff)<<16);
202 if ( error_called
) {
209 static IMAGE
*glob_image
;
210 static long *glob_datap
;
211 static int glob_width
, glob_z
, glob_ysize
;
219 getrow(glob_image
, buf
, (glob_ysize
-1-y
), glob_z
);
221 getrow(glob_image
, buf
, y
, glob_z
);
229 char *datap
= (char *)glob_datap
+ y
*glob_width
;
230 int width
= glob_width
;
233 *datap
++ = (*buf
++) & 0xff;
241 long *datap
= glob_datap
+ y
*glob_width
;
242 int width
= glob_width
;
245 *datap
++ = (*buf
++) & 0xff;
252 long *datap
= glob_datap
+ y
*glob_width
;
253 int width
= glob_width
;
256 *datap
++ |= ((*buf
++) & 0xff) << (glob_z
*8);
260 xscale(image
, xsize
, ysize
, zsize
, datap
, xnew
, ynew
, fmode
, blur
)
262 int xsize
, ysize
, zsize
;
274 filterzoom(xs_get
, xs_put_c
, xsize
, ysize
,
275 xnew
, ynew
, fmode
, blur
);
278 filterzoom(xs_get
, xs_put_0
, xsize
, ysize
,
279 xnew
, ynew
, fmode
, blur
);
281 filterzoom(xs_get
, xs_put_12
, xsize
, ysize
,
282 xnew
, ynew
, fmode
, blur
);
284 filterzoom(xs_get
, xs_put_12
, xsize
, ysize
,
285 xnew
, ynew
, fmode
, blur
);
291 imgfile_readscaled(self
, args
)
297 int xsize
, ysize
, zsize
;
300 static short rs
[8192], gs
[8192], bs
[8192];
302 int xwtd
, ywtd
, xorig
, yorig
;
310 int yfirst
, ylast
, ystep
;
313 ** Parse args. Funny, since arg 4 and 5 are optional
314 ** (filter name and blur factor). Also, 4 or 5 arguments indicates
315 ** extended scale algorithm in stead of simple-minded pixel drop/dup.
318 cnt
= PyTuple_Size(args
);
321 if ( !PyArg_Parse(args
, "(siisd)",
322 &fname
, &xwtd
, &ywtd
, &filter
, &blur
) )
324 } else if ( cnt
== 4 ) {
326 if ( !PyArg_Parse(args
, "(siis)",
327 &fname
, &xwtd
, &ywtd
, &filter
) )
330 } else if ( !PyArg_Parse(args
, "(sii)", &fname
, &xwtd
, &ywtd
) )
334 ** Check parameters, open file and check type, rows, etc.
337 if ( strcmp(filter
, "impulse") == 0 )
339 else if ( strcmp( filter
, "box") == 0 )
341 else if ( strcmp( filter
, "triangle") == 0 )
343 else if ( strcmp( filter
, "quadratic") == 0 )
345 else if ( strcmp( filter
, "gaussian") == 0 )
348 PyErr_SetString(ImgfileError
, "Unknown filter type");
353 if ( (image
= imgfile_open(fname
)) == NULL
)
356 if ( image
->colormap
!= CM_NORMAL
) {
358 PyErr_SetString(ImgfileError
,
359 "Can only handle CM_NORMAL images");
362 if ( BPP(image
->type
) != 1 ) {
364 PyErr_SetString(ImgfileError
,
365 "Can't handle imgfiles with bpp!=1");
368 xsize
= image
->xsize
;
369 ysize
= image
->ysize
;
370 zsize
= image
->zsize
;
371 if ( zsize
!= 1 && zsize
!= 3) {
373 PyErr_SetString(ImgfileError
,
374 "Can only handle 1 or 3 byte pixels");
377 if ( xsize
> 8192 ) {
379 PyErr_SetString(ImgfileError
,
380 "Can't handle image with > 8192 columns");
384 if ( zsize
== 3 ) zsize
= 4;
385 rv
= PyString_FromStringAndSize(NULL
, xwtd
*ywtd
*zsize
);
390 PyFPE_START_PROTECT("readscaled", return 0)
391 xfac
= (float)xsize
/(float)xwtd
;
392 yfac
= (float)ysize
/(float)ywtd
;
393 PyFPE_END_PROTECT(yfac
)
394 cdatap
= PyString_AsString(rv
);
395 idatap
= (long *)cdatap
;
398 xscale(image
, xsize
, ysize
, zsize
,
399 idatap
, xwtd
, ywtd
, fmode
, blur
);
410 for ( y
=yfirst
; y
!= ylast
&& !error_called
; y
+= ystep
) {
411 yorig
= (int)(y
*yfac
);
413 getrow(image
, rs
, yorig
, 0);
414 for(x
=0; x
<xwtd
; x
++ ) {
415 *cdatap
++ = rs
[(int)(x
*xfac
)];
418 getrow(image
, rs
, yorig
, 0);
419 getrow(image
, gs
, yorig
, 1);
420 getrow(image
, bs
, yorig
, 2);
421 for(x
=0; x
<xwtd
; x
++ ) {
422 xorig
= (int)(x
*xfac
);
423 *idatap
++ = (rs
[xorig
] & 0xff) |
424 ((gs
[xorig
] & 0xff)<<8) |
425 ((bs
[xorig
] & 0xff)<<16);
431 if ( error_called
) {
439 imgfile_getsizes(self
, args
)
447 if ( !PyArg_Parse(args
, "s", &fname
) )
450 if ( (image
= imgfile_open(fname
)) == NULL
)
452 rv
= Py_BuildValue("(iii)", image
->xsize
, image
->ysize
, image
->zsize
);
458 imgfile_write(self
, args
)
464 int xsize
, ysize
, zsize
, len
;
467 short rs
[8192], gs
[8192], bs
[8192];
471 int yfirst
, ylast
, ystep
;
474 if ( !PyArg_Parse(args
, "(ss#iii)",
475 &fname
, &cdatap
, &len
, &xsize
, &ysize
, &zsize
) )
478 if ( zsize
!= 1 && zsize
!= 3 ) {
479 PyErr_SetString(ImgfileError
,
480 "Can only handle 1 or 3 byte pixels");
483 if ( len
!= xsize
* ysize
* (zsize
== 1 ? 1 : 4) ) {
484 PyErr_SetString(ImgfileError
, "Data does not match sizes");
487 if ( xsize
> 8192 ) {
488 PyErr_SetString(ImgfileError
,
489 "Can't handle image with > 8192 columns");
495 image
=iopen(fname
, "w", RLE(1), 3, xsize
, ysize
, zsize
);
497 if ( ! error_called
) {
499 PyErr_SetFromErrno(ImgfileError
);
501 PyErr_SetString(ImgfileError
,
502 "Can't create image file");
507 idatap
= (long *)cdatap
;
518 for ( y
=yfirst
; y
!= ylast
&& !error_called
; y
+= ystep
) {
520 for( x
=0; x
<xsize
; x
++ )
522 putrow(image
, rs
, y
, 0);
524 for( x
=0; x
<xsize
; x
++ ) {
527 g
= (rgb
>> 8 ) & 0xff;
528 b
= (rgb
>> 16 ) & 0xff;
533 putrow(image
, rs
, y
, 0);
534 putrow(image
, gs
, y
, 1);
535 putrow(image
, bs
, y
, 2);
547 static PyMethodDef imgfile_methods
[] = {
548 { "getsizes", imgfile_getsizes
},
549 { "read", imgfile_read
},
550 { "readscaled", imgfile_readscaled
, 1},
551 { "write", imgfile_write
},
552 { "ttob", imgfile_ttob
},
553 { NULL
, NULL
} /* Sentinel */
561 m
= Py_InitModule("imgfile", imgfile_methods
);
562 d
= PyModule_GetDict(m
);
563 ImgfileError
= PyErr_NewException("imgfile.error", NULL
, NULL
);
564 if (ImgfileError
!= NULL
)
565 PyDict_SetItemString(d
, "error", ImgfileError
);