blob: 5bab5403670a7654cbef9a351ac6a2d808efe475 [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
49imgfile_error(str)
Roger E. Masse7f33e401996-12-20 21:56:08 +000050 char *str;
Guido van Rossum3e941971992-03-23 18:21:32 +000051{
Roger E. Masse7f33e401996-12-20 21:56:08 +000052 PyErr_SetString(ImgfileError, str);
53 error_called = 1;
54 return; /* To imglib, which will return a failure indicator */
Guido van Rossum3e941971992-03-23 18:21:32 +000055}
Guido van Rossumaa9de671992-03-04 16:40:03 +000056
Guido van Rossuma5f61381992-09-03 20:41:22 +000057
58/* Open an image file and return a pointer to it.
59 Make sure we raise an exception if we fail. */
60
61static IMAGE *
Guido van Rossum2c4be641992-06-03 17:06:36 +000062imgfile_open(fname)
Roger E. Masse7f33e401996-12-20 21:56:08 +000063 char *fname;
Guido van Rossum2c4be641992-06-03 17:06:36 +000064{
Roger E. Masse7f33e401996-12-20 21:56:08 +000065 IMAGE *image;
66 i_seterror(imgfile_error);
67 error_called = 0;
68 errno = 0;
69 if ( (image = iopen(fname, "r")) == NULL ) {
70 /* Error may already be set by imgfile_error */
71 if ( !error_called ) {
72 if (errno)
73 PyErr_SetFromErrno(ImgfileError);
74 else
75 PyErr_SetString(ImgfileError,
76 "Can't open image file");
77 }
78 return NULL;
Guido van Rossumaa9de671992-03-04 16:40:03 +000079 }
Roger E. Masse7f33e401996-12-20 21:56:08 +000080 return image;
81}
82
83static PyObject *
84imgfile_ttob(self, args)
85 PyObject *self;
86PyObject *args;
87{
88 int newval;
89 PyObject *rv;
90
91 if (!PyArg_Parse(args, "i", &newval))
92 return NULL;
93 rv = PyInt_FromLong(top_to_bottom);
94 top_to_bottom = newval;
95 return rv;
96}
97
98static PyObject *
99imgfile_read(self, args)
100 PyObject *self;
101PyObject *args;
102{
103 char *fname;
104 PyObject *rv;
105 int xsize, ysize, zsize;
106 char *cdatap;
107 long *idatap;
108 static short rs[8192], gs[8192], bs[8192];
109 int x, y;
110 IMAGE *image;
111 int yfirst, ylast, ystep;
112
113 if ( !PyArg_Parse(args, "s", &fname) )
114 return NULL;
115
116 if ( (image = imgfile_open(fname)) == NULL )
117 return NULL;
118
119 if ( image->colormap != CM_NORMAL ) {
120 iclose(image);
121 PyErr_SetString(ImgfileError,
122 "Can only handle CM_NORMAL images");
123 return NULL;
124 }
125 if ( BPP(image->type) != 1 ) {
126 iclose(image);
127 PyErr_SetString(ImgfileError,
128 "Can't handle imgfiles with bpp!=1");
129 return NULL;
130 }
131 xsize = image->xsize;
132 ysize = image->ysize;
133 zsize = image->zsize;
134 if ( zsize != 1 && zsize != 3) {
135 iclose(image);
136 PyErr_SetString(ImgfileError,
137 "Can only handle 1 or 3 byte pixels");
138 return NULL;
139 }
140 if ( xsize > 8192 ) {
141 iclose(image);
142 PyErr_SetString(ImgfileError,
143 "Can't handle image with > 8192 columns");
144 return NULL;
145 }
146
147 if ( zsize == 3 ) zsize = 4;
148 rv = PyString_FromStringAndSize((char *)NULL, xsize*ysize*zsize);
149 if ( rv == NULL ) {
150 iclose(image);
151 return NULL;
152 }
153 cdatap = PyString_AsString(rv);
154 idatap = (long *)cdatap;
155
156 if (top_to_bottom) {
157 yfirst = ysize-1;
158 ylast = -1;
159 ystep = -1;
160 } else {
161 yfirst = 0;
162 ylast = ysize;
163 ystep = 1;
164 }
165 for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
166 if ( zsize == 1 ) {
167 getrow(image, rs, y, 0);
168 for(x=0; x<xsize; x++ )
169 *cdatap++ = rs[x];
170 } else {
171 getrow(image, rs, y, 0);
172 getrow(image, gs, y, 1);
173 getrow(image, bs, y, 2);
174 for(x=0; x<xsize; x++ )
175 *idatap++ = (rs[x] & 0xff) |
176 ((gs[x] & 0xff)<<8) |
177 ((bs[x] & 0xff)<<16);
178 }
179 }
180 iclose(image);
181 if ( error_called ) {
182 Py_DECREF(rv);
183 return NULL;
184 }
185 return rv;
Guido van Rossumaa9de671992-03-04 16:40:03 +0000186}
187
Guido van Rossum234f9421993-06-17 12:35:49 +0000188static IMAGE *glob_image;
189static long *glob_datap;
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +0000190static int glob_width, glob_z, glob_ysize;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000191
Guido van Rossuma376cc51996-12-05 23:43:35 +0000192static void
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000193xs_get(buf, y)
Roger E. Masse7f33e401996-12-20 21:56:08 +0000194 short *buf;
195int y;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000196{
Roger E. Masse7f33e401996-12-20 21:56:08 +0000197 if (top_to_bottom)
198 getrow(glob_image, buf, (glob_ysize-1-y), glob_z);
199 else
200 getrow(glob_image, buf, y, glob_z);
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000201}
202
Guido van Rossuma376cc51996-12-05 23:43:35 +0000203static void
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000204xs_put_c(buf, y)
Roger E. Masse7f33e401996-12-20 21:56:08 +0000205 short *buf;
206int y;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000207{
Roger E. Masse7f33e401996-12-20 21:56:08 +0000208 char *datap = (char *)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}
214
Guido van Rossuma376cc51996-12-05 23:43:35 +0000215static void
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000216xs_put_0(buf, y)
Roger E. Masse7f33e401996-12-20 21:56:08 +0000217 short *buf;
218int y;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000219{
Roger E. Masse7f33e401996-12-20 21:56:08 +0000220 long *datap = glob_datap + y*glob_width;
221 int width = glob_width;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000222
Roger E. Masse7f33e401996-12-20 21:56:08 +0000223 while ( width-- )
224 *datap++ = (*buf++) & 0xff;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000225}
Guido van Rossuma376cc51996-12-05 23:43:35 +0000226static void
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000227xs_put_12(buf, y)
Roger E. Masse7f33e401996-12-20 21:56:08 +0000228 short *buf;
229int y;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000230{
Roger E. Masse7f33e401996-12-20 21:56:08 +0000231 long *datap = glob_datap + y*glob_width;
232 int width = glob_width;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000233
Roger E. Masse7f33e401996-12-20 21:56:08 +0000234 while ( width-- )
235 *datap++ |= ((*buf++) & 0xff) << (glob_z*8);
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000236}
237
238static void
239xscale(image, xsize, ysize, zsize, datap, xnew, ynew, fmode, blur)
Roger E. Masse7f33e401996-12-20 21:56:08 +0000240 IMAGE *image;
241int xsize, ysize, zsize;
242long *datap;
243int xnew, ynew;
244int fmode;
245double blur;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000246{
Roger E. Masse7f33e401996-12-20 21:56:08 +0000247 glob_image = image;
248 glob_datap = datap;
249 glob_width = xnew;
250 glob_ysize = ysize;
251 if ( zsize == 1 ) {
252 glob_z = 0;
253 filterzoom(xs_get, xs_put_c, xsize, ysize,
254 xnew, ynew, fmode, blur);
255 } else {
256 glob_z = 0;
257 filterzoom(xs_get, xs_put_0, xsize, ysize,
258 xnew, ynew, fmode, blur);
259 glob_z = 1;
260 filterzoom(xs_get, xs_put_12, xsize, ysize,
261 xnew, ynew, fmode, blur);
262 glob_z = 2;
263 filterzoom(xs_get, xs_put_12, xsize, ysize,
264 xnew, ynew, fmode, blur);
265 }
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000266}
267
Guido van Rossuma5f61381992-09-03 20:41:22 +0000268
Roger E. Masse7f33e401996-12-20 21:56:08 +0000269static PyObject *
Guido van Rossum2c4be641992-06-03 17:06:36 +0000270imgfile_readscaled(self, args)
Roger E. Masse7f33e401996-12-20 21:56:08 +0000271 PyObject *self;
272PyObject *args;
Guido van Rossum2c4be641992-06-03 17:06:36 +0000273{
Roger E. Masse7f33e401996-12-20 21:56:08 +0000274 char *fname;
275 PyObject *rv;
276 int xsize, ysize, zsize;
277 char *cdatap;
278 long *idatap;
279 static short rs[8192], gs[8192], bs[8192];
280 int x, y;
281 int xwtd, ywtd, xorig, yorig;
282 float xfac, yfac;
283 int cnt;
284 IMAGE *image;
285 char *filter;
286 double blur;
287 int extended;
288 int fmode = 0;
289 int yfirst, ylast, ystep;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000290
Roger E. Masse7f33e401996-12-20 21:56:08 +0000291 /*
292 ** Parse args. Funny, since arg 4 and 5 are optional
293 ** (filter name and blur factor). Also, 4 or 5 arguments indicates
294 ** extended scale algorithm in stead of simple-minded pixel drop/dup.
295 */
296 extended = 0;
297 cnt = PyTuple_Size(args);
298 if ( cnt == 5 ) {
299 extended = 1;
300 if ( !PyArg_Parse(args, "(siisd)",
301 &fname, &xwtd, &ywtd, &filter, &blur) )
302 return NULL;
303 } else if ( cnt == 4 ) {
304 extended = 1;
305 if ( !PyArg_Parse(args, "(siis)",
306 &fname, &xwtd, &ywtd, &filter) )
307 return NULL;
308 blur = 1.0;
309 } else if ( !PyArg_Parse(args, "(sii)", &fname, &xwtd, &ywtd) )
310 return NULL;
Guido van Rossum2c4be641992-06-03 17:06:36 +0000311
Roger E. Masse7f33e401996-12-20 21:56:08 +0000312 /*
313 ** Check parameters, open file and check type, rows, etc.
314 */
315 if ( extended ) {
316 if ( strcmp(filter, "impulse") == 0 )
317 fmode = IMPULSE;
318 else if ( strcmp( filter, "box") == 0 )
319 fmode = BOX;
320 else if ( strcmp( filter, "triangle") == 0 )
321 fmode = TRIANGLE;
322 else if ( strcmp( filter, "quadratic") == 0 )
323 fmode = QUADRATIC;
324 else if ( strcmp( filter, "gaussian") == 0 )
325 fmode = GAUSSIAN;
326 else {
327 PyErr_SetString(ImgfileError, "Unknown filter type");
328 return NULL;
329 }
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000330 }
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000331
Roger E. Masse7f33e401996-12-20 21:56:08 +0000332 if ( (image = imgfile_open(fname)) == NULL )
333 return NULL;
Guido van Rossum2c4be641992-06-03 17:06:36 +0000334
Roger E. Masse7f33e401996-12-20 21:56:08 +0000335 if ( image->colormap != CM_NORMAL ) {
336 iclose(image);
337 PyErr_SetString(ImgfileError,
338 "Can only handle CM_NORMAL images");
339 return NULL;
340 }
341 if ( BPP(image->type) != 1 ) {
342 iclose(image);
343 PyErr_SetString(ImgfileError,
344 "Can't handle imgfiles with bpp!=1");
345 return NULL;
346 }
347 xsize = image->xsize;
348 ysize = image->ysize;
349 zsize = image->zsize;
350 if ( zsize != 1 && zsize != 3) {
351 iclose(image);
352 PyErr_SetString(ImgfileError,
353 "Can only handle 1 or 3 byte pixels");
354 return NULL;
355 }
356 if ( xsize > 8192 ) {
357 iclose(image);
358 PyErr_SetString(ImgfileError,
359 "Can't handle image with > 8192 columns");
360 return NULL;
361 }
Guido van Rossum2c4be641992-06-03 17:06:36 +0000362
Roger E. Masse7f33e401996-12-20 21:56:08 +0000363 if ( zsize == 3 ) zsize = 4;
364 rv = PyString_FromStringAndSize(NULL, xwtd*ywtd*zsize);
365 if ( rv == NULL ) {
366 iclose(image);
367 return NULL;
368 }
Guido van Rossum52fa3a61997-02-14 22:59:58 +0000369 PyFPE_START_PROTECT("readscaled", return 0)
Roger E. Masse7f33e401996-12-20 21:56:08 +0000370 xfac = (float)xsize/(float)xwtd;
371 yfac = (float)ysize/(float)ywtd;
Guido van Rossum45b83911997-03-14 04:32:50 +0000372 PyFPE_END_PROTECT(yfac)
Roger E. Masse7f33e401996-12-20 21:56:08 +0000373 cdatap = PyString_AsString(rv);
374 idatap = (long *)cdatap;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000375
Roger E. Masse7f33e401996-12-20 21:56:08 +0000376 if ( extended ) {
377 xscale(image, xsize, ysize, zsize,
378 idatap, xwtd, ywtd, fmode, blur);
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +0000379 } else {
Roger E. Masse7f33e401996-12-20 21:56:08 +0000380 if (top_to_bottom) {
381 yfirst = ywtd-1;
382 ylast = -1;
383 ystep = -1;
384 } else {
385 yfirst = 0;
386 ylast = ywtd;
387 ystep = 1;
388 }
389 for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
390 yorig = (int)(y*yfac);
391 if ( zsize == 1 ) {
392 getrow(image, rs, yorig, 0);
393 for(x=0; x<xwtd; x++ ) {
394 *cdatap++ = rs[(int)(x*xfac)];
395 }
396 } else {
397 getrow(image, rs, yorig, 0);
398 getrow(image, gs, yorig, 1);
399 getrow(image, bs, yorig, 2);
400 for(x=0; x<xwtd; x++ ) {
401 xorig = (int)(x*xfac);
402 *idatap++ = (rs[xorig] & 0xff) |
403 ((gs[xorig] & 0xff)<<8) |
404 ((bs[xorig] & 0xff)<<16);
405 }
406 }
407 }
408 }
409 iclose(image);
410 if ( error_called ) {
411 Py_DECREF(rv);
412 return NULL;
413 }
414 return rv;
415}
416
417static PyObject *
418imgfile_getsizes(self, args)
419 PyObject *self;
420PyObject *args;
421{
422 char *fname;
423 PyObject *rv;
424 IMAGE *image;
425
426 if ( !PyArg_Parse(args, "s", &fname) )
427 return NULL;
428
429 if ( (image = imgfile_open(fname)) == NULL )
430 return NULL;
431 rv = Py_BuildValue("(iii)", image->xsize, image->ysize, image->zsize);
432 iclose(image);
433 return rv;
434}
435
436static PyObject *
437imgfile_write(self, args)
438 PyObject *self;
439PyObject *args;
440{
441 IMAGE *image;
442 char *fname;
443 int xsize, ysize, zsize, len;
444 char *cdatap;
445 long *idatap;
446 short rs[8192], gs[8192], bs[8192];
447 short r, g, b;
448 long rgb;
449 int x, y;
450 int yfirst, ylast, ystep;
451
452
453 if ( !PyArg_Parse(args, "(ss#iii)",
454 &fname, &cdatap, &len, &xsize, &ysize, &zsize) )
455 return NULL;
456
457 if ( zsize != 1 && zsize != 3 ) {
458 PyErr_SetString(ImgfileError,
459 "Can only handle 1 or 3 byte pixels");
460 return NULL;
461 }
462 if ( len != xsize * ysize * (zsize == 1 ? 1 : 4) ) {
463 PyErr_SetString(ImgfileError, "Data does not match sizes");
464 return NULL;
465 }
466 if ( xsize > 8192 ) {
467 PyErr_SetString(ImgfileError,
468 "Can't handle image with > 8192 columns");
469 return NULL;
470 }
471
472 error_called = 0;
473 errno = 0;
474 image =iopen(fname, "w", RLE(1), 3, xsize, ysize, zsize);
475 if ( image == 0 ) {
476 if ( ! error_called ) {
477 if (errno)
478 PyErr_SetFromErrno(ImgfileError);
479 else
480 PyErr_SetString(ImgfileError,
481 "Can't create image file");
482 }
483 return NULL;
484 }
485
486 idatap = (long *)cdatap;
487
488 if (top_to_bottom) {
489 yfirst = ysize-1;
490 ylast = -1;
491 ystep = -1;
492 } else {
493 yfirst = 0;
494 ylast = ysize;
495 ystep = 1;
Sjoerd Mullendera9c3c221993-10-11 12:54:31 +0000496 }
497 for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
Roger E. Masse7f33e401996-12-20 21:56:08 +0000498 if ( zsize == 1 ) {
499 for( x=0; x<xsize; x++ )
500 rs[x] = *cdatap++;
501 putrow(image, rs, y, 0);
502 } else {
503 for( x=0; x<xsize; x++ ) {
504 rgb = *idatap++;
505 r = rgb & 0xff;
506 g = (rgb >> 8 ) & 0xff;
507 b = (rgb >> 16 ) & 0xff;
508 rs[x] = r;
509 gs[x] = g;
510 bs[x] = b;
511 }
512 putrow(image, rs, y, 0);
513 putrow(image, gs, y, 1);
514 putrow(image, bs, y, 2);
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000515 }
Guido van Rossum2c4be641992-06-03 17:06:36 +0000516 }
Roger E. Masse7f33e401996-12-20 21:56:08 +0000517 iclose(image);
518 if ( error_called )
519 return NULL;
520 Py_INCREF(Py_None);
521 return Py_None;
Jack Jansen3accf981992-08-20 11:54:27 +0000522
523}
Guido van Rossumaa9de671992-03-04 16:40:03 +0000524
Guido van Rossuma5f61381992-09-03 20:41:22 +0000525
Roger E. Masse7f33e401996-12-20 21:56:08 +0000526static PyMethodDef imgfile_methods[] = {
527 { "getsizes", imgfile_getsizes },
528 { "read", imgfile_read },
529 { "readscaled", imgfile_readscaled, 1},
530 { "write", imgfile_write },
531 { "ttob", imgfile_ttob },
532 { NULL, NULL } /* Sentinel */
Guido van Rossumaa9de671992-03-04 16:40:03 +0000533};
534
535
536void
537initimgfile()
538{
Roger E. Masse7f33e401996-12-20 21:56:08 +0000539 PyObject *m, *d;
540 m = Py_InitModule("imgfile", imgfile_methods);
541 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000542 ImgfileError = PyErr_NewException("imgfile.error", NULL, NULL);
543 if (ImgfileError != NULL)
544 PyDict_SetItemString(d, "error", ImgfileError);
Guido van Rossumaa9de671992-03-04 16:40:03 +0000545}
Roger E. Masse7f33e401996-12-20 21:56:08 +0000546
547
548