blob: a6db0266d2a02adc5a1e1edcf9953e469b74ea01 [file] [log] [blame]
Guido van Rossumaa9de671992-03-04 16:40:03 +00001/***********************************************************
Guido van Rossum34679b71993-01-26 13:33:44 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
Guido van Rossumaa9de671992-03-04 16:40:03 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossuma5f61381992-09-03 20:41:22 +000025/* IMGFILE module - Interface to sgi libimage */
Guido van Rossumaa9de671992-03-04 16:40:03 +000026
Guido van Rossum2c4be641992-06-03 17:06:36 +000027/* XXX This modele should be done better at some point. It should return
Guido van Rossumaa9de671992-03-04 16:40:03 +000028** an object of image file class, and have routines to manipulate these
29** image files in a neater way (so you can get rgb images off a greyscale
30** file, for instance, or do a straight display without having to get the
31** image bits into python, etc).
Jack Jansen3c2eb5c1993-01-19 15:17:13 +000032**
33** Warning: this module is very non-reentrant (esp. the readscaled stuff)
Guido van Rossumaa9de671992-03-04 16:40:03 +000034*/
35
36#include "allobjects.h"
37#include "modsupport.h"
38
39#include <gl/image.h>
Guido van Rossuma5f61381992-09-03 20:41:22 +000040#include <errno.h>
Guido van Rossumaa9de671992-03-04 16:40:03 +000041
Jack Jansen09cbf9a1993-01-19 15:33:13 +000042#include "/usr/people/4Dgifts/iristools/include/izoom.h"
Jack Jansen3c2eb5c1993-01-19 15:17:13 +000043
Guido van Rossuma5f61381992-09-03 20:41:22 +000044static object * ImgfileError; /* Exception we raise for various trouble */
Guido van Rossumaa9de671992-03-04 16:40:03 +000045
Guido van Rossumaa9de671992-03-04 16:40:03 +000046
Guido van Rossuma5f61381992-09-03 20:41:22 +000047/* The image library does not always call the error hander :-(,
48 therefore we have a global variable indicating that it was called.
49 It is cleared by imgfile_open(). */
Guido van Rossumaa9de671992-03-04 16:40:03 +000050
Guido van Rossum3e941971992-03-23 18:21:32 +000051static int error_called;
52
Guido van Rossuma5f61381992-09-03 20:41:22 +000053
54/* The error handler */
55
Guido van Rossum3e941971992-03-23 18:21:32 +000056static imgfile_error(str)
57 char *str;
58{
59 err_setstr(ImgfileError, str);
60 error_called = 1;
Guido van Rossum9bfef441993-03-29 10:43:31 +000061 return; /* To imglib, which will return a failure indicator */
Guido van Rossum3e941971992-03-23 18:21:32 +000062}
Guido van Rossumaa9de671992-03-04 16:40:03 +000063
Guido van Rossuma5f61381992-09-03 20:41:22 +000064
65/* Open an image file and return a pointer to it.
66 Make sure we raise an exception if we fail. */
67
68static IMAGE *
Guido van Rossum2c4be641992-06-03 17:06:36 +000069imgfile_open(fname)
Guido van Rossumaa9de671992-03-04 16:40:03 +000070 char *fname;
Guido van Rossum2c4be641992-06-03 17:06:36 +000071{
Guido van Rossuma5f61381992-09-03 20:41:22 +000072 IMAGE *image;
Guido van Rossum3e941971992-03-23 18:21:32 +000073 i_seterror(imgfile_error);
74 error_called = 0;
Guido van Rossuma5f61381992-09-03 20:41:22 +000075 errno = 0;
76 if ( (image = iopen(fname, "r")) == NULL ) {
Guido van Rossum3e941971992-03-23 18:21:32 +000077 /* Error may already be set by imgfile_error */
Guido van Rossuma5f61381992-09-03 20:41:22 +000078 if ( !error_called ) {
79 if (errno)
80 err_errno(ImgfileError);
81 else
82 err_setstr(ImgfileError, "Can't open image file");
83 }
84 return NULL;
Guido van Rossumaa9de671992-03-04 16:40:03 +000085 }
Guido van Rossuma5f61381992-09-03 20:41:22 +000086 return image;
Guido van Rossumaa9de671992-03-04 16:40:03 +000087}
88
Guido van Rossuma5f61381992-09-03 20:41:22 +000089
Guido van Rossumaa9de671992-03-04 16:40:03 +000090static object *
91imgfile_read(self, args)
92 object *self;
93 object *args;
94{
95 char *fname;
96 object *rv;
97 int xsize, ysize, zsize;
98 char *cdatap;
99 long *idatap;
100 static short rs[8192], gs[8192], bs[8192];
101 int x, y;
Guido van Rossuma5f61381992-09-03 20:41:22 +0000102 IMAGE *image;
Guido van Rossumaa9de671992-03-04 16:40:03 +0000103
Guido van Rossum2c4be641992-06-03 17:06:36 +0000104 if ( !getargs(args, "s", &fname) )
Guido van Rossuma5f61381992-09-03 20:41:22 +0000105 return NULL;
Guido van Rossum2c4be641992-06-03 17:06:36 +0000106
Guido van Rossuma5f61381992-09-03 20:41:22 +0000107 if ( (image = imgfile_open(fname)) == NULL )
Guido van Rossumaa9de671992-03-04 16:40:03 +0000108 return NULL;
109
110 if ( image->colormap != CM_NORMAL ) {
Guido van Rossuma5f61381992-09-03 20:41:22 +0000111 iclose(image);
Guido van Rossumaa9de671992-03-04 16:40:03 +0000112 err_setstr(ImgfileError, "Can only handle CM_NORMAL images");
113 return NULL;
114 }
115 if ( BPP(image->type) != 1 ) {
Guido van Rossuma5f61381992-09-03 20:41:22 +0000116 iclose(image);
117 err_setstr(ImgfileError, "Can't handle imgfiles with bpp!=1");
Guido van Rossumaa9de671992-03-04 16:40:03 +0000118 return NULL;
119 }
120 xsize = image->xsize;
121 ysize = image->ysize;
122 zsize = image->zsize;
123 if ( zsize != 1 && zsize != 3) {
Guido van Rossuma5f61381992-09-03 20:41:22 +0000124 iclose(image);
Guido van Rossumaa9de671992-03-04 16:40:03 +0000125 err_setstr(ImgfileError, "Can only handle 1 or 3 byte pixels");
126 return NULL;
127 }
Guido van Rossuma5f61381992-09-03 20:41:22 +0000128 if ( xsize > 8192 ) {
129 iclose(image);
130 err_setstr(ImgfileError, "Can't handle image with > 8192 columns");
131 return NULL;
132 }
Guido van Rossumaa9de671992-03-04 16:40:03 +0000133
134 if ( zsize == 3 ) zsize = 4;
Guido van Rossuma5f61381992-09-03 20:41:22 +0000135 rv = newsizedstringobject((char *)NULL, xsize*ysize*zsize);
136 if ( rv == NULL ) {
137 iclose(image);
Guido van Rossumaa9de671992-03-04 16:40:03 +0000138 return NULL;
Guido van Rossuma5f61381992-09-03 20:41:22 +0000139 }
Guido van Rossumaa9de671992-03-04 16:40:03 +0000140 cdatap = getstringvalue(rv);
141 idatap = (long *)cdatap;
Guido van Rossum3e941971992-03-23 18:21:32 +0000142 for ( y=0; y < ysize && !error_called; y++ ) {
Guido van Rossumaa9de671992-03-04 16:40:03 +0000143 if ( zsize == 1 ) {
144 getrow(image, rs, y, 0);
145 for(x=0; x<xsize; x++ )
146 *cdatap++ = rs[x];
147 } else {
148 getrow(image, rs, y, 0);
149 getrow(image, gs, y, 1);
150 getrow(image, bs, y, 2);
151 for(x=0; x<xsize; x++ )
152 *idatap++ = (rs[x] & 0xff) |
153 ((gs[x] & 0xff)<<8) |
154 ((bs[x] & 0xff)<<16);
155 }
156 }
Jack Jansen3accf981992-08-20 11:54:27 +0000157 iclose(image);
Guido van Rossum3e941971992-03-23 18:21:32 +0000158 if ( error_called ) {
159 DECREF(rv);
160 return NULL;
161 }
Guido van Rossumaa9de671992-03-04 16:40:03 +0000162 return rv;
163}
164
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000165IMAGE *glob_image;
166long *glob_datap;
167int glob_width, glob_z;
168
169static
170xs_get(buf, y)
171 short *buf;
172 int y;
173{
174 getrow(glob_image, buf, y, glob_z);
175}
176
177static
178xs_put_c(buf, y)
179 short *buf;
180 int y;
181{
182 char *datap = (char *)glob_datap + y*glob_width;
183 int width = glob_width;
184
185 while ( width-- )
186 *datap++ = (*buf++) & 0xff;
187}
188
189static
190xs_put_0(buf, y)
191 short *buf;
192 int y;
193{
194 long *datap = glob_datap + y*glob_width;
195 int width = glob_width;
196
197 while ( width-- )
198 *datap++ = (*buf++) & 0xff;
199}
200static
201xs_put_12(buf, y)
202 short *buf;
203 int y;
204{
205 long *datap = glob_datap + y*glob_width;
206 int width = glob_width;
207
208 while ( width-- )
209 *datap++ |= ((*buf++) & 0xff) << (glob_z*8);
210}
211
212static void
213xscale(image, xsize, ysize, zsize, datap, xnew, ynew, fmode, blur)
214 IMAGE *image;
215 int xsize, ysize, zsize;
216 long *datap;
217 int xnew, ynew;
218 int fmode;
219 double blur;
220{
221 glob_image = image;
222 glob_datap = datap;
223 glob_width = xnew;
224 if ( zsize == 1 ) {
225 glob_z = 0;
226 filterzoom(xs_get, xs_put_c, xsize, ysize, xnew, ynew, fmode, blur);
227 } else {
228 glob_z = 0;
229 filterzoom(xs_get, xs_put_0, xsize, ysize, xnew, ynew, fmode, blur);
230 glob_z = 1;
231 filterzoom(xs_get, xs_put_12, xsize, ysize, xnew, ynew, fmode, blur);
232 glob_z = 2;
233 filterzoom(xs_get, xs_put_12, xsize, ysize, xnew, ynew, fmode, blur);
234 }
235}
236
Guido van Rossuma5f61381992-09-03 20:41:22 +0000237
Guido van Rossumaa9de671992-03-04 16:40:03 +0000238static object *
Guido van Rossum2c4be641992-06-03 17:06:36 +0000239imgfile_readscaled(self, args)
240 object *self;
241 object *args;
242{
243 char *fname;
244 object *rv;
245 int xsize, ysize, zsize;
246 char *cdatap;
247 long *idatap;
248 static short rs[8192], gs[8192], bs[8192];
249 int x, y;
250 int xwtd, ywtd, xorig, yorig;
251 float xfac, yfac;
252 int cnt;
Guido van Rossuma5f61381992-09-03 20:41:22 +0000253 IMAGE *image;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000254 char *filter;
255 double blur;
256 int extended;
257 int fmode;
258
259 /*
260 ** Parse args. Funny, since arg 4 and 5 are optional
261 ** (filter name and blur factor). Also, 4 or 5 arguments indicates
262 ** extended scale algorithm in stead of simple-minded pixel drop/dup.
263 */
264 extended = 0;
265 cnt = gettuplesize(args);
266 if ( cnt == 5 ) {
267 extended = 1;
268 if ( !getargs(args, "(siisd)", &fname, &xwtd, &ywtd, &filter, &blur) )
269 return NULL;
270 } else if ( cnt == 4 ) {
271 extended = 1;
272 if ( !getargs(args, "(siis)", &fname, &xwtd, &ywtd, &filter) )
273 return NULL;
274 blur = 1.0;
275 } else if ( !getargs(args, "(sii)", &fname, &xwtd, &ywtd) )
Guido van Rossuma5f61381992-09-03 20:41:22 +0000276 return NULL;
Guido van Rossum2c4be641992-06-03 17:06:36 +0000277
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000278 /*
279 ** Check parameters, open file and check type, rows, etc.
280 */
281 if ( extended ) {
282 if ( strcmp(filter, "impulse") == 0 ) fmode = IMPULSE;
283 else if ( strcmp( filter, "box") == 0 ) fmode = BOX;
284 else if ( strcmp( filter, "triangle") == 0 ) fmode = TRIANGLE;
285 else if ( strcmp( filter, "quadratic") == 0 ) fmode = QUADRATIC;
286 else if ( strcmp( filter, "gaussian") == 0 ) fmode = GAUSSIAN;
287 else {
288 err_setstr(ImgfileError, "Unknown filter type");
289 return NULL;
290 }
291 }
292
Guido van Rossuma5f61381992-09-03 20:41:22 +0000293 if ( (image = imgfile_open(fname)) == NULL )
Guido van Rossum2c4be641992-06-03 17:06:36 +0000294 return NULL;
295
296 if ( image->colormap != CM_NORMAL ) {
Guido van Rossuma5f61381992-09-03 20:41:22 +0000297 iclose(image);
Guido van Rossum2c4be641992-06-03 17:06:36 +0000298 err_setstr(ImgfileError, "Can only handle CM_NORMAL images");
299 return NULL;
300 }
301 if ( BPP(image->type) != 1 ) {
Guido van Rossuma5f61381992-09-03 20:41:22 +0000302 iclose(image);
303 err_setstr(ImgfileError, "Can't handle imgfiles with bpp!=1");
Guido van Rossum2c4be641992-06-03 17:06:36 +0000304 return NULL;
305 }
306 xsize = image->xsize;
307 ysize = image->ysize;
308 zsize = image->zsize;
309 if ( zsize != 1 && zsize != 3) {
Guido van Rossuma5f61381992-09-03 20:41:22 +0000310 iclose(image);
Guido van Rossum2c4be641992-06-03 17:06:36 +0000311 err_setstr(ImgfileError, "Can only handle 1 or 3 byte pixels");
312 return NULL;
313 }
Guido van Rossuma5f61381992-09-03 20:41:22 +0000314 if ( xsize > 8192 ) {
315 iclose(image);
316 err_setstr(ImgfileError, "Can't handle image with > 8192 columns");
317 return NULL;
318 }
Guido van Rossum2c4be641992-06-03 17:06:36 +0000319
320 if ( zsize == 3 ) zsize = 4;
321 rv = newsizedstringobject(NULL, xwtd*ywtd*zsize);
Guido van Rossuma5f61381992-09-03 20:41:22 +0000322 if ( rv == NULL ) {
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000323 iclose(image);
324 return NULL;
Guido van Rossuma5f61381992-09-03 20:41:22 +0000325 }
Guido van Rossum2c4be641992-06-03 17:06:36 +0000326 xfac = (float)xsize/(float)xwtd;
327 yfac = (float)ysize/(float)ywtd;
Guido van Rossum2c4be641992-06-03 17:06:36 +0000328 cdatap = getstringvalue(rv);
329 idatap = (long *)cdatap;
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000330
331 if ( extended ) {
332 xscale(image, xsize, ysize, zsize, idatap, xwtd, ywtd, fmode, blur);
333 } else {
334 for ( y=0; y < ywtd && !error_called; y++ ) {
335 yorig = (int)(y*yfac);
336 if ( zsize == 1 ) {
337 getrow(image, rs, yorig, 0);
338 for(x=0; x<xwtd; x++ ) {
339 *cdatap++ = rs[(int)(x*xfac)];
340 }
341 } else {
342 getrow(image, rs, yorig, 0);
343 getrow(image, gs, yorig, 1);
344 getrow(image, bs, yorig, 2);
345 for(x=0; x<xwtd; x++ ) {
346 xorig = (int)(x*xfac);
347 *idatap++ = (rs[xorig] & 0xff) |
348 ((gs[xorig] & 0xff)<<8) |
349 ((bs[xorig] & 0xff)<<16);
350 }
351 }
Guido van Rossum2c4be641992-06-03 17:06:36 +0000352 }
353 }
Guido van Rossuma5f61381992-09-03 20:41:22 +0000354 iclose(image);
Guido van Rossum2c4be641992-06-03 17:06:36 +0000355 if ( error_called ) {
356 DECREF(rv);
357 return NULL;
358 }
359 return rv;
360}
361
362static object *
Guido van Rossumaa9de671992-03-04 16:40:03 +0000363imgfile_getsizes(self, args)
364 object *self;
365 object *args;
366{
367 char *fname;
368 object *rv;
Guido van Rossuma5f61381992-09-03 20:41:22 +0000369 IMAGE *image;
Guido van Rossumaa9de671992-03-04 16:40:03 +0000370
Guido van Rossum2c4be641992-06-03 17:06:36 +0000371 if ( !getargs(args, "s", &fname) )
Guido van Rossuma5f61381992-09-03 20:41:22 +0000372 return NULL;
Guido van Rossum2c4be641992-06-03 17:06:36 +0000373
Guido van Rossuma5f61381992-09-03 20:41:22 +0000374 if ( (image = imgfile_open(fname)) == NULL )
Guido van Rossumaa9de671992-03-04 16:40:03 +0000375 return NULL;
Guido van Rossuma5f61381992-09-03 20:41:22 +0000376 rv = mkvalue("(iii)", image->xsize, image->ysize, image->zsize);
377 iclose(image);
Guido van Rossumaa9de671992-03-04 16:40:03 +0000378 return rv;
379}
380
Jack Jansen3accf981992-08-20 11:54:27 +0000381static object *
382imgfile_write(self, args)
383 object *self;
384 object *args;
385{
386 IMAGE *image;
387 char *fname;
388 int xsize, ysize, zsize, len;
389 char *cdatap;
390 long *idatap;
391 short rs[8192], gs[8192], bs[8192];
392 short r, g, b;
393 long rgb;
394 int x, y;
395
396 if ( !getargs(args, "(ss#iii)",
397 &fname, &cdatap, &len, &xsize, &ysize, &zsize) )
Guido van Rossuma5f61381992-09-03 20:41:22 +0000398 return NULL;
Jack Jansen3accf981992-08-20 11:54:27 +0000399
400 if ( zsize != 1 && zsize != 3 ) {
401 err_setstr(ImgfileError, "Can only handle 1 or 3 byte pixels");
Guido van Rossuma5f61381992-09-03 20:41:22 +0000402 return NULL;
Jack Jansen3accf981992-08-20 11:54:27 +0000403 }
Guido van Rossuma5f61381992-09-03 20:41:22 +0000404 if ( len != xsize * ysize * (zsize == 1 ? 1 : 4) ) {
Jack Jansen3accf981992-08-20 11:54:27 +0000405 err_setstr(ImgfileError, "Data does not match sizes");
Guido van Rossuma5f61381992-09-03 20:41:22 +0000406 return NULL;
407 }
408 if ( xsize > 8192 ) {
409 err_setstr(ImgfileError, "Can't handle image with > 8192 columns");
410 return NULL;
Jack Jansen3accf981992-08-20 11:54:27 +0000411 }
412
Guido van Rossuma5f61381992-09-03 20:41:22 +0000413 error_called = 0;
414 errno = 0;
Jack Jansen3accf981992-08-20 11:54:27 +0000415 image =iopen(fname, "w", RLE(1), 3, xsize, ysize, zsize);
416 if ( image == 0 ) {
Guido van Rossuma5f61381992-09-03 20:41:22 +0000417 if ( ! error_called ) {
418 if (errno)
419 err_errno(ImgfileError);
420 else
421 err_setstr(ImgfileError, "Can't create image file");
422 }
423 return NULL;
Jack Jansen3accf981992-08-20 11:54:27 +0000424 }
425
426 idatap = (long *)cdatap;
427
428 for( y=0; y<ysize && !error_called; y++ ) {
429 if ( zsize == 1 ) {
430 for( x=0; x<xsize; x++ )
431 rs[x] = *cdatap++;
432 putrow(image, rs, y, 0);
433 } else {
434 for( x=0; x<xsize; x++ ) {
435 rgb = *idatap++;
436 r = rgb & 0xff;
437 g = (rgb >> 8 ) & 0xff;
438 b = (rgb >> 16 ) & 0xff;
439 rs[x] = r;
440 gs[x] = g;
441 bs[x] = b;
442 }
443 putrow(image, rs, y, 0);
444 putrow(image, gs, y, 1);
445 putrow(image, bs, y, 2);
446 }
447 }
448 iclose(image);
449 if ( error_called )
Guido van Rossuma5f61381992-09-03 20:41:22 +0000450 return NULL;
Jack Jansen3accf981992-08-20 11:54:27 +0000451 INCREF(None);
452 return None;
453
454}
Guido van Rossumaa9de671992-03-04 16:40:03 +0000455
Guido van Rossuma5f61381992-09-03 20:41:22 +0000456
Guido van Rossumaa9de671992-03-04 16:40:03 +0000457static struct methodlist imgfile_methods[] = {
Guido van Rossum2c4be641992-06-03 17:06:36 +0000458 { "getsizes", imgfile_getsizes },
459 { "read", imgfile_read },
Jack Jansen3c2eb5c1993-01-19 15:17:13 +0000460 { "readscaled", imgfile_readscaled, 1},
Jack Jansen3accf981992-08-20 11:54:27 +0000461 { "write", imgfile_write },
Guido van Rossuma5f61381992-09-03 20:41:22 +0000462 { NULL, NULL } /* Sentinel */
Guido van Rossumaa9de671992-03-04 16:40:03 +0000463};
464
465
466void
467initimgfile()
468{
469 object *m, *d;
470 m = initmodule("imgfile", imgfile_methods);
471 d = getmoduledict(m);
472 ImgfileError = newstringobject("imgfile.error");
Guido van Rossuma5f61381992-09-03 20:41:22 +0000473 if ( ImgfileError == NULL || dictinsert(d, "error", ImgfileError) )
Guido van Rossumaa9de671992-03-04 16:40:03 +0000474 fatal("can't define imgfile.error");
475}