blob: 0b9dd54b511a1e313f9aa37cbf30e821a8851fdf [file] [log] [blame]
Guido van Rossumaa9de671992-03-04 16:40:03 +00001/***********************************************************
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00002Copyright (c) 2000, BeOpen.com.
3Copyright (c) 1995-2000, Corporation for National Research Initiatives.
4Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
5All rights reserved.
Guido van Rossumaa9de671992-03-04 16:40:03 +00006
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00007See the file "Misc/COPYRIGHT" for information on usage and
8redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossumaa9de671992-03-04 16:40:03 +00009******************************************************************/
10
Guido van Rossuma5f61381992-09-03 20:41:22 +000011/* IMGFILE module - Interface to sgi libimage */
Guido van Rossumaa9de671992-03-04 16:40:03 +000012
Guido van Rossum2c4be641992-06-03 17:06:36 +000013/* XXX This modele should be done better at some point. It should return
Guido van Rossumaa9de671992-03-04 16:40:03 +000014** an object of image file class, and have routines to manipulate these
15** image files in a neater way (so you can get rgb images off a greyscale
16** file, for instance, or do a straight display without having to get the
17** image bits into python, etc).
Jack Jansen3c2eb5c1993-01-19 15:17:13 +000018**
19** Warning: this module is very non-reentrant (esp. the readscaled stuff)
Guido van Rossumaa9de671992-03-04 16:40:03 +000020*/
21
Roger E. Masse7f33e401996-12-20 21:56:08 +000022#include "Python.h"
Guido van Rossumaa9de671992-03-04 16:40:03 +000023
24#include <gl/image.h>
25
Jack Jansen09cbf9a1993-01-19 15:33:13 +000026#include "/usr/people/4Dgifts/iristools/include/izoom.h"
Jack Jansen3c2eb5c1993-01-19 15:17:13 +000027
Guido van Rossum665f9191996-12-09 18:49:42 +000028/* Bunch of missing extern decls; keep gcc -Wall happy... */
29extern void i_seterror();
30extern void iclose();
31extern void filterzoom();
32extern void putrow();
33extern void getrow();
34
Roger E. Masse7f33e401996-12-20 21:56:08 +000035static PyObject * ImgfileError; /* Exception we raise for various trouble */
Guido van Rossumaa9de671992-03-04 16:40:03 +000036
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +000037static int top_to_bottom; /* True if we want top-to-bottom images */
Guido van Rossumaa9de671992-03-04 16:40:03 +000038
Guido van Rossuma5f61381992-09-03 20:41:22 +000039/* The image library does not always call the error hander :-(,
40 therefore we have a global variable indicating that it was called.
41 It is cleared by imgfile_open(). */
Guido van Rossumaa9de671992-03-04 16:40:03 +000042
Guido van Rossum3e941971992-03-23 18:21:32 +000043static int error_called;
44
Guido van Rossuma5f61381992-09-03 20:41:22 +000045
46/* The error handler */
47
Guido van Rossuma376cc51996-12-05 23:43:35 +000048static void
Peter Schneider-Kamp6a850272000-07-10 17:04:33 +000049imgfile_error(char *str)
Guido van Rossum3e941971992-03-23 18:21:32 +000050{
Roger E. Masse7f33e401996-12-20 21:56:08 +000051 PyErr_SetString(ImgfileError, str);
52 error_called = 1;
53 return; /* To imglib, which will return a failure indicator */
Guido van Rossum3e941971992-03-23 18:21:32 +000054}
Guido van Rossumaa9de671992-03-04 16:40:03 +000055
Guido van Rossuma5f61381992-09-03 20:41:22 +000056
57/* Open an image file and return a pointer to it.
58 Make sure we raise an exception if we fail. */
59
60static IMAGE *
Peter Schneider-Kamp6a850272000-07-10 17:04:33 +000061imgfile_open(char *fname)
Guido van Rossum2c4be641992-06-03 17:06:36 +000062{
Roger E. Masse7f33e401996-12-20 21:56:08 +000063 IMAGE *image;
64 i_seterror(imgfile_error);
65 error_called = 0;
66 errno = 0;
67 if ( (image = iopen(fname, "r")) == NULL ) {
68 /* Error may already be set by imgfile_error */
69 if ( !error_called ) {
70 if (errno)
71 PyErr_SetFromErrno(ImgfileError);
72 else
73 PyErr_SetString(ImgfileError,
74 "Can't open image file");
75 }
76 return NULL;
Guido van Rossumaa9de671992-03-04 16:40:03 +000077 }
Roger E. Masse7f33e401996-12-20 21:56:08 +000078 return image;
79}
80
81static PyObject *
Peter Schneider-Kamp6a850272000-07-10 17:04:33 +000082imgfile_ttob(PyObject *self, PyObject *args)
Roger E. Masse7f33e401996-12-20 21:56:08 +000083{
84 int newval;
85 PyObject *rv;
86
87 if (!PyArg_Parse(args, "i", &newval))
88 return NULL;
89 rv = PyInt_FromLong(top_to_bottom);
90 top_to_bottom = newval;
91 return rv;
92}
93
94static PyObject *
Peter Schneider-Kamp6a850272000-07-10 17:04:33 +000095imgfile_read(PyObject *self, PyObject *args)
Roger E. Masse7f33e401996-12-20 21:56:08 +000096{
97 char *fname;
98 PyObject *rv;
99 int xsize, ysize, zsize;
100 char *cdatap;
101 long *idatap;
102 static short rs[8192], gs[8192], bs[8192];
103 int x, y;
104 IMAGE *image;
105 int yfirst, ylast, ystep;
106
107 if ( !PyArg_Parse(args, "s", &fname) )
108 return NULL;
109
110 if ( (image = imgfile_open(fname)) == NULL )
111 return NULL;
112
113 if ( image->colormap != CM_NORMAL ) {
114 iclose(image);
115 PyErr_SetString(ImgfileError,
116 "Can only handle CM_NORMAL images");
117 return NULL;
118 }
119 if ( BPP(image->type) != 1 ) {
120 iclose(image);
121 PyErr_SetString(ImgfileError,
122 "Can't handle imgfiles with bpp!=1");
123 return NULL;
124 }
125 xsize = image->xsize;
126 ysize = image->ysize;
127 zsize = image->zsize;
128 if ( zsize != 1 && zsize != 3) {
129 iclose(image);
130 PyErr_SetString(ImgfileError,
131 "Can only handle 1 or 3 byte pixels");
132 return NULL;
133 }
134 if ( xsize > 8192 ) {
135 iclose(image);
136 PyErr_SetString(ImgfileError,
137 "Can't handle image with > 8192 columns");
138 return NULL;
139 }
140
141 if ( zsize == 3 ) zsize = 4;
142 rv = PyString_FromStringAndSize((char *)NULL, xsize*ysize*zsize);
143 if ( rv == NULL ) {
144 iclose(image);
145 return NULL;
146 }
147 cdatap = PyString_AsString(rv);
148 idatap = (long *)cdatap;
149
150 if (top_to_bottom) {
151 yfirst = ysize-1;
152 ylast = -1;
153 ystep = -1;
154 } else {
155 yfirst = 0;
156 ylast = ysize;
157 ystep = 1;
158 }
159 for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
160 if ( zsize == 1 ) {
161 getrow(image, rs, y, 0);
162 for(x=0; x<xsize; x++ )
163 *cdatap++ = rs[x];
164 } else {
165 getrow(image, rs, y, 0);
166 getrow(image, gs, y, 1);
167 getrow(image, bs, y, 2);
168 for(x=0; x<xsize; x++ )
169 *idatap++ = (rs[x] & 0xff) |
170 ((gs[x] & 0xff)<<8) |
171 ((bs[x] & 0xff)<<16);
172 }
173 }
174 iclose(image);
175 if ( error_called ) {
176 Py_DECREF(rv);
177 return NULL;
178 }
179 return rv;
Guido van Rossumaa9de671992-03-04 16:40:03 +0000180}
181
Guido van Rossum234f9421993-06-17 12:35:49 +0000182static IMAGE *glob_image;
183static long *glob_datap;
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +0000184static int glob_width, glob_z, glob_ysize;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000185
Guido van Rossuma376cc51996-12-05 23:43:35 +0000186static void
Peter Schneider-Kamp6a850272000-07-10 17:04:33 +0000187xs_get(short *buf, int y)
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000188{
Roger E. Masse7f33e401996-12-20 21:56:08 +0000189 if (top_to_bottom)
190 getrow(glob_image, buf, (glob_ysize-1-y), glob_z);
191 else
192 getrow(glob_image, buf, y, glob_z);
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000193}
194
Guido van Rossuma376cc51996-12-05 23:43:35 +0000195static void
Peter Schneider-Kamp6a850272000-07-10 17:04:33 +0000196xs_put_c(short *buf, int y)
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000197{
Roger E. Masse7f33e401996-12-20 21:56:08 +0000198 char *datap = (char *)glob_datap + y*glob_width;
199 int width = glob_width;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000200
Roger E. Masse7f33e401996-12-20 21:56:08 +0000201 while ( width-- )
202 *datap++ = (*buf++) & 0xff;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000203}
204
Guido van Rossuma376cc51996-12-05 23:43:35 +0000205static void
Peter Schneider-Kamp6a850272000-07-10 17:04:33 +0000206xs_put_0(short *buf, int y)
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000207{
Roger E. Masse7f33e401996-12-20 21:56:08 +0000208 long *datap = glob_datap + y*glob_width;
209 int width = glob_width;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000210
Roger E. Masse7f33e401996-12-20 21:56:08 +0000211 while ( width-- )
212 *datap++ = (*buf++) & 0xff;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000213}
Guido van Rossuma376cc51996-12-05 23:43:35 +0000214static void
Peter Schneider-Kamp6a850272000-07-10 17:04:33 +0000215xs_put_12(short *buf, int y)
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000216{
Roger E. Masse7f33e401996-12-20 21:56:08 +0000217 long *datap = glob_datap + y*glob_width;
218 int width = glob_width;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000219
Roger E. Masse7f33e401996-12-20 21:56:08 +0000220 while ( width-- )
221 *datap++ |= ((*buf++) & 0xff) << (glob_z*8);
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000222}
223
224static void
Peter Schneider-Kamp6a850272000-07-10 17:04:33 +0000225xscale(IMAGE *image, int xsize, int ysize, int zsize,
226 long *datap, int xnew, int ynew, int fmode, double blur)
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000227{
Roger E. Masse7f33e401996-12-20 21:56:08 +0000228 glob_image = image;
229 glob_datap = datap;
230 glob_width = xnew;
231 glob_ysize = ysize;
232 if ( zsize == 1 ) {
233 glob_z = 0;
234 filterzoom(xs_get, xs_put_c, xsize, ysize,
235 xnew, ynew, fmode, blur);
236 } else {
237 glob_z = 0;
238 filterzoom(xs_get, xs_put_0, xsize, ysize,
239 xnew, ynew, fmode, blur);
240 glob_z = 1;
241 filterzoom(xs_get, xs_put_12, xsize, ysize,
242 xnew, ynew, fmode, blur);
243 glob_z = 2;
244 filterzoom(xs_get, xs_put_12, xsize, ysize,
245 xnew, ynew, fmode, blur);
246 }
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000247}
248
Guido van Rossuma5f61381992-09-03 20:41:22 +0000249
Roger E. Masse7f33e401996-12-20 21:56:08 +0000250static PyObject *
Peter Schneider-Kamp6a850272000-07-10 17:04:33 +0000251imgfile_readscaled(PyObject *self, PyObject *args)
Guido van Rossum2c4be641992-06-03 17:06:36 +0000252{
Roger E. Masse7f33e401996-12-20 21:56:08 +0000253 char *fname;
254 PyObject *rv;
255 int xsize, ysize, zsize;
256 char *cdatap;
257 long *idatap;
258 static short rs[8192], gs[8192], bs[8192];
259 int x, y;
260 int xwtd, ywtd, xorig, yorig;
261 float xfac, yfac;
262 int cnt;
263 IMAGE *image;
264 char *filter;
265 double blur;
266 int extended;
267 int fmode = 0;
268 int yfirst, ylast, ystep;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000269
Roger E. Masse7f33e401996-12-20 21:56:08 +0000270 /*
271 ** Parse args. Funny, since arg 4 and 5 are optional
272 ** (filter name and blur factor). Also, 4 or 5 arguments indicates
273 ** extended scale algorithm in stead of simple-minded pixel drop/dup.
274 */
275 extended = 0;
276 cnt = PyTuple_Size(args);
277 if ( cnt == 5 ) {
278 extended = 1;
279 if ( !PyArg_Parse(args, "(siisd)",
280 &fname, &xwtd, &ywtd, &filter, &blur) )
281 return NULL;
282 } else if ( cnt == 4 ) {
283 extended = 1;
284 if ( !PyArg_Parse(args, "(siis)",
285 &fname, &xwtd, &ywtd, &filter) )
286 return NULL;
287 blur = 1.0;
288 } else if ( !PyArg_Parse(args, "(sii)", &fname, &xwtd, &ywtd) )
289 return NULL;
Guido van Rossum2c4be641992-06-03 17:06:36 +0000290
Roger E. Masse7f33e401996-12-20 21:56:08 +0000291 /*
292 ** Check parameters, open file and check type, rows, etc.
293 */
294 if ( extended ) {
295 if ( strcmp(filter, "impulse") == 0 )
296 fmode = IMPULSE;
297 else if ( strcmp( filter, "box") == 0 )
298 fmode = BOX;
299 else if ( strcmp( filter, "triangle") == 0 )
300 fmode = TRIANGLE;
301 else if ( strcmp( filter, "quadratic") == 0 )
302 fmode = QUADRATIC;
303 else if ( strcmp( filter, "gaussian") == 0 )
304 fmode = GAUSSIAN;
305 else {
306 PyErr_SetString(ImgfileError, "Unknown filter type");
307 return NULL;
308 }
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000309 }
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000310
Roger E. Masse7f33e401996-12-20 21:56:08 +0000311 if ( (image = imgfile_open(fname)) == NULL )
312 return NULL;
Guido van Rossum2c4be641992-06-03 17:06:36 +0000313
Roger E. Masse7f33e401996-12-20 21:56:08 +0000314 if ( image->colormap != CM_NORMAL ) {
315 iclose(image);
316 PyErr_SetString(ImgfileError,
317 "Can only handle CM_NORMAL images");
318 return NULL;
319 }
320 if ( BPP(image->type) != 1 ) {
321 iclose(image);
322 PyErr_SetString(ImgfileError,
323 "Can't handle imgfiles with bpp!=1");
324 return NULL;
325 }
326 xsize = image->xsize;
327 ysize = image->ysize;
328 zsize = image->zsize;
329 if ( zsize != 1 && zsize != 3) {
330 iclose(image);
331 PyErr_SetString(ImgfileError,
332 "Can only handle 1 or 3 byte pixels");
333 return NULL;
334 }
335 if ( xsize > 8192 ) {
336 iclose(image);
337 PyErr_SetString(ImgfileError,
338 "Can't handle image with > 8192 columns");
339 return NULL;
340 }
Guido van Rossum2c4be641992-06-03 17:06:36 +0000341
Roger E. Masse7f33e401996-12-20 21:56:08 +0000342 if ( zsize == 3 ) zsize = 4;
343 rv = PyString_FromStringAndSize(NULL, xwtd*ywtd*zsize);
344 if ( rv == NULL ) {
345 iclose(image);
346 return NULL;
347 }
Guido van Rossum52fa3a61997-02-14 22:59:58 +0000348 PyFPE_START_PROTECT("readscaled", return 0)
Roger E. Masse7f33e401996-12-20 21:56:08 +0000349 xfac = (float)xsize/(float)xwtd;
350 yfac = (float)ysize/(float)ywtd;
Guido van Rossum45b83911997-03-14 04:32:50 +0000351 PyFPE_END_PROTECT(yfac)
Roger E. Masse7f33e401996-12-20 21:56:08 +0000352 cdatap = PyString_AsString(rv);
353 idatap = (long *)cdatap;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000354
Roger E. Masse7f33e401996-12-20 21:56:08 +0000355 if ( extended ) {
356 xscale(image, xsize, ysize, zsize,
357 idatap, xwtd, ywtd, fmode, blur);
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +0000358 } else {
Roger E. Masse7f33e401996-12-20 21:56:08 +0000359 if (top_to_bottom) {
360 yfirst = ywtd-1;
361 ylast = -1;
362 ystep = -1;
363 } else {
364 yfirst = 0;
365 ylast = ywtd;
366 ystep = 1;
367 }
368 for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
369 yorig = (int)(y*yfac);
370 if ( zsize == 1 ) {
371 getrow(image, rs, yorig, 0);
372 for(x=0; x<xwtd; x++ ) {
373 *cdatap++ = rs[(int)(x*xfac)];
374 }
375 } else {
376 getrow(image, rs, yorig, 0);
377 getrow(image, gs, yorig, 1);
378 getrow(image, bs, yorig, 2);
379 for(x=0; x<xwtd; x++ ) {
380 xorig = (int)(x*xfac);
381 *idatap++ = (rs[xorig] & 0xff) |
382 ((gs[xorig] & 0xff)<<8) |
383 ((bs[xorig] & 0xff)<<16);
384 }
385 }
386 }
387 }
388 iclose(image);
389 if ( error_called ) {
390 Py_DECREF(rv);
391 return NULL;
392 }
393 return rv;
394}
395
396static PyObject *
Peter Schneider-Kamp6a850272000-07-10 17:04:33 +0000397imgfile_getsizes(PyObject *self, PyObject *args)
Roger E. Masse7f33e401996-12-20 21:56:08 +0000398{
399 char *fname;
400 PyObject *rv;
401 IMAGE *image;
402
403 if ( !PyArg_Parse(args, "s", &fname) )
404 return NULL;
405
406 if ( (image = imgfile_open(fname)) == NULL )
407 return NULL;
408 rv = Py_BuildValue("(iii)", image->xsize, image->ysize, image->zsize);
409 iclose(image);
410 return rv;
411}
412
413static PyObject *
Peter Schneider-Kamp6a850272000-07-10 17:04:33 +0000414imgfile_write(PyObject *self, PyObject *args)
Roger E. Masse7f33e401996-12-20 21:56:08 +0000415{
416 IMAGE *image;
417 char *fname;
418 int xsize, ysize, zsize, len;
419 char *cdatap;
420 long *idatap;
421 short rs[8192], gs[8192], bs[8192];
422 short r, g, b;
423 long rgb;
424 int x, y;
425 int yfirst, ylast, ystep;
426
427
428 if ( !PyArg_Parse(args, "(ss#iii)",
429 &fname, &cdatap, &len, &xsize, &ysize, &zsize) )
430 return NULL;
431
432 if ( zsize != 1 && zsize != 3 ) {
433 PyErr_SetString(ImgfileError,
434 "Can only handle 1 or 3 byte pixels");
435 return NULL;
436 }
437 if ( len != xsize * ysize * (zsize == 1 ? 1 : 4) ) {
438 PyErr_SetString(ImgfileError, "Data does not match sizes");
439 return NULL;
440 }
441 if ( xsize > 8192 ) {
442 PyErr_SetString(ImgfileError,
443 "Can't handle image with > 8192 columns");
444 return NULL;
445 }
446
447 error_called = 0;
448 errno = 0;
449 image =iopen(fname, "w", RLE(1), 3, xsize, ysize, zsize);
450 if ( image == 0 ) {
451 if ( ! error_called ) {
452 if (errno)
453 PyErr_SetFromErrno(ImgfileError);
454 else
455 PyErr_SetString(ImgfileError,
456 "Can't create image file");
457 }
458 return NULL;
459 }
460
461 idatap = (long *)cdatap;
462
463 if (top_to_bottom) {
464 yfirst = ysize-1;
465 ylast = -1;
466 ystep = -1;
467 } else {
468 yfirst = 0;
469 ylast = ysize;
470 ystep = 1;
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +0000471 }
472 for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
Roger E. Masse7f33e401996-12-20 21:56:08 +0000473 if ( zsize == 1 ) {
474 for( x=0; x<xsize; x++ )
475 rs[x] = *cdatap++;
476 putrow(image, rs, y, 0);
477 } else {
478 for( x=0; x<xsize; x++ ) {
479 rgb = *idatap++;
480 r = rgb & 0xff;
481 g = (rgb >> 8 ) & 0xff;
482 b = (rgb >> 16 ) & 0xff;
483 rs[x] = r;
484 gs[x] = g;
485 bs[x] = b;
486 }
487 putrow(image, rs, y, 0);
488 putrow(image, gs, y, 1);
489 putrow(image, bs, y, 2);
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000490 }
Guido van Rossum2c4be641992-06-03 17:06:36 +0000491 }
Roger E. Masse7f33e401996-12-20 21:56:08 +0000492 iclose(image);
493 if ( error_called )
494 return NULL;
495 Py_INCREF(Py_None);
496 return Py_None;
Jack Jansen3accf981992-08-20 11:54:27 +0000497
498}
Guido van Rossumaa9de671992-03-04 16:40:03 +0000499
Guido van Rossuma5f61381992-09-03 20:41:22 +0000500
Roger E. Masse7f33e401996-12-20 21:56:08 +0000501static PyMethodDef imgfile_methods[] = {
502 { "getsizes", imgfile_getsizes },
503 { "read", imgfile_read },
504 { "readscaled", imgfile_readscaled, 1},
505 { "write", imgfile_write },
506 { "ttob", imgfile_ttob },
507 { NULL, NULL } /* Sentinel */
Guido van Rossumaa9de671992-03-04 16:40:03 +0000508};
509
510
511void
512initimgfile()
513{
Roger E. Masse7f33e401996-12-20 21:56:08 +0000514 PyObject *m, *d;
515 m = Py_InitModule("imgfile", imgfile_methods);
516 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000517 ImgfileError = PyErr_NewException("imgfile.error", NULL, NULL);
518 if (ImgfileError != NULL)
519 PyDict_SetItemString(d, "error", ImgfileError);
Guido van Rossumaa9de671992-03-04 16:40:03 +0000520}
Roger E. Masse7f33e401996-12-20 21:56:08 +0000521
522
523