• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* IMGFILE module - Interface to sgi libimage */
3 
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).
9 **
10 ** Warning: this module is very non-reentrant (esp. the readscaled stuff)
11 */
12 
13 #include "Python.h"
14 
15 #include <gl/image.h>
16 
17 #include "/usr/people/4Dgifts/iristools/include/izoom.h"
18 
19 /* Bunch of missing extern decls; keep gcc -Wall happy... */
20 extern void i_seterror();
21 extern void iclose();
22 extern void filterzoom();
23 extern void putrow();
24 extern void getrow();
25 
26 static PyObject * ImgfileError; /* Exception we raise for various trouble */
27 
28 static int top_to_bottom;       /* True if we want top-to-bottom images */
29 
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(). */
33 
34 static int error_called;
35 
36 
37 /* The error handler */
38 
39 static void
imgfile_error(char * str)40 imgfile_error(char *str)
41 {
42     PyErr_SetString(ImgfileError, str);
43     error_called = 1;
44     return;     /* To imglib, which will return a failure indicator */
45 }
46 
47 
48 /* Open an image file and return a pointer to it.
49    Make sure we raise an exception if we fail. */
50 
51 static IMAGE *
imgfile_open(char * fname)52 imgfile_open(char *fname)
53 {
54     IMAGE *image;
55     i_seterror(imgfile_error);
56     error_called = 0;
57     errno = 0;
58     if ( (image = iopen(fname, "r")) == NULL ) {
59         /* Error may already be set by imgfile_error */
60         if ( !error_called ) {
61             if (errno)
62                 PyErr_SetFromErrno(ImgfileError);
63             else
64                 PyErr_SetString(ImgfileError,
65                                 "Can't open image file");
66         }
67         return NULL;
68     }
69     return image;
70 }
71 
72 static PyObject *
imgfile_ttob(PyObject * self,PyObject * args)73 imgfile_ttob(PyObject *self, PyObject *args)
74 {
75     int newval;
76     PyObject *rv;
77 
78     if (!PyArg_ParseTuple(args, "i:ttob", &newval))
79         return NULL;
80     rv = PyInt_FromLong(top_to_bottom);
81     top_to_bottom = newval;
82     return rv;
83 }
84 
85 static PyObject *
imgfile_read(PyObject * self,PyObject * args)86 imgfile_read(PyObject *self, PyObject *args)
87 {
88     char *fname;
89     PyObject *rv;
90     int xsize, ysize, zsize;
91     char *cdatap;
92     long *idatap;
93     static short rs[8192], gs[8192], bs[8192];
94     int x, y;
95     IMAGE *image;
96     int yfirst, ylast, ystep;
97 
98     if ( !PyArg_ParseTuple(args, "s:read", &fname) )
99         return NULL;
100 
101     if ( (image = imgfile_open(fname)) == NULL )
102         return NULL;
103 
104     if ( image->colormap != CM_NORMAL ) {
105         iclose(image);
106         PyErr_SetString(ImgfileError,
107                         "Can only handle CM_NORMAL images");
108         return NULL;
109     }
110     if ( BPP(image->type) != 1 ) {
111         iclose(image);
112         PyErr_SetString(ImgfileError,
113                         "Can't handle imgfiles with bpp!=1");
114         return NULL;
115     }
116     xsize = image->xsize;
117     ysize = image->ysize;
118     zsize = image->zsize;
119     if ( zsize != 1 && zsize != 3) {
120         iclose(image);
121         PyErr_SetString(ImgfileError,
122                         "Can only handle 1 or 3 byte pixels");
123         return NULL;
124     }
125     if ( xsize > 8192 ) {
126         iclose(image);
127         PyErr_SetString(ImgfileError,
128                         "Can't handle image with > 8192 columns");
129         return NULL;
130     }
131 
132     if ( zsize == 3 ) zsize = 4;
133     rv = PyString_FromStringAndSize((char *)NULL, xsize*ysize*zsize);
134     if ( rv == NULL ) {
135         iclose(image);
136         return NULL;
137     }
138     cdatap = PyString_AsString(rv);
139     idatap = (long *)cdatap;
140 
141     if (top_to_bottom) {
142         yfirst = ysize-1;
143         ylast = -1;
144         ystep = -1;
145     } else {
146         yfirst = 0;
147         ylast = ysize;
148         ystep = 1;
149     }
150     for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
151         if ( zsize == 1 ) {
152             getrow(image, rs, y, 0);
153             for(x=0; x<xsize; x++ )
154                 *cdatap++ = rs[x];
155         } else {
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);
163         }
164     }
165     iclose(image);
166     if ( error_called ) {
167         Py_DECREF(rv);
168         return NULL;
169     }
170     return rv;
171 }
172 
173 static IMAGE *glob_image;
174 static long *glob_datap;
175 static int glob_width, glob_z, glob_ysize;
176 
177 static void
xs_get(short * buf,int y)178 xs_get(short *buf, int y)
179 {
180     if (top_to_bottom)
181         getrow(glob_image, buf, (glob_ysize-1-y), glob_z);
182     else
183         getrow(glob_image, buf, y, glob_z);
184 }
185 
186 static void
xs_put_c(short * buf,int y)187 xs_put_c(short *buf, int y)
188 {
189     char *datap = (char *)glob_datap + y*glob_width;
190     int width = glob_width;
191 
192     while ( width-- )
193         *datap++ = (*buf++) & 0xff;
194 }
195 
196 static void
xs_put_0(short * buf,int y)197 xs_put_0(short *buf, int y)
198 {
199     long *datap = glob_datap + y*glob_width;
200     int width = glob_width;
201 
202     while ( width-- )
203         *datap++ = (*buf++) & 0xff;
204 }
205 static void
xs_put_12(short * buf,int y)206 xs_put_12(short *buf, int y)
207 {
208     long *datap = glob_datap + y*glob_width;
209     int width = glob_width;
210 
211     while ( width-- )
212         *datap++ |= ((*buf++) & 0xff) << (glob_z*8);
213 }
214 
215 static void
xscale(IMAGE * image,int xsize,int ysize,int zsize,long * datap,int xnew,int ynew,int fmode,double blur)216 xscale(IMAGE *image, int xsize, int ysize, int zsize,
217        long *datap, int xnew, int ynew, int fmode, double blur)
218 {
219     glob_image = image;
220     glob_datap = datap;
221     glob_width = xnew;
222     glob_ysize = ysize;
223     if ( zsize == 1 ) {
224         glob_z = 0;
225         filterzoom(xs_get, xs_put_c, xsize, ysize,
226                    xnew, ynew, fmode, blur);
227     } else {
228         glob_z = 0;
229         filterzoom(xs_get, xs_put_0, xsize, ysize,
230                    xnew, ynew, fmode, blur);
231         glob_z = 1;
232         filterzoom(xs_get, xs_put_12, xsize, ysize,
233                    xnew, ynew, fmode, blur);
234         glob_z = 2;
235         filterzoom(xs_get, xs_put_12, xsize, ysize,
236                    xnew, ynew, fmode, blur);
237     }
238 }
239 
240 
241 static PyObject *
imgfile_readscaled(PyObject * self,PyObject * args)242 imgfile_readscaled(PyObject *self, PyObject *args)
243 {
244     char *fname;
245     PyObject *rv;
246     int xsize, ysize, zsize;
247     char *cdatap;
248     long *idatap;
249     static short rs[8192], gs[8192], bs[8192];
250     int x, y;
251     int xwtd, ywtd, xorig, yorig;
252     float xfac, yfac;
253     IMAGE *image;
254     char *filter;
255     double blur = 1.0;
256     int extended;
257     int fmode = 0;
258     int yfirst, ylast, ystep;
259 
260     /*
261     ** Parse args. Funny, since arg 4 and 5 are optional
262     ** (filter name and blur factor). Also, 4 or 5 arguments indicates
263     ** extended scale algorithm in stead of simple-minded pixel drop/dup.
264     */
265     extended = PyTuple_Size(args) >= 4;
266     if ( !PyArg_ParseTuple(args, "sii|sd",
267                            &fname, &xwtd, &ywtd, &filter, &blur) )
268         return NULL;
269 
270     /*
271     ** Check parameters, open file and check type, rows, etc.
272     */
273     if ( extended ) {
274         if ( strcmp(filter, "impulse") == 0 )
275             fmode = IMPULSE;
276         else if ( strcmp( filter, "box") == 0 )
277             fmode = BOX;
278         else if ( strcmp( filter, "triangle") == 0 )
279             fmode = TRIANGLE;
280         else if ( strcmp( filter, "quadratic") == 0 )
281             fmode = QUADRATIC;
282         else if ( strcmp( filter, "gaussian") == 0 )
283             fmode = GAUSSIAN;
284         else {
285             PyErr_SetString(ImgfileError, "Unknown filter type");
286             return NULL;
287         }
288     }
289 
290     if ( (image = imgfile_open(fname)) == NULL )
291         return NULL;
292 
293     if ( image->colormap != CM_NORMAL ) {
294         iclose(image);
295         PyErr_SetString(ImgfileError,
296                         "Can only handle CM_NORMAL images");
297         return NULL;
298     }
299     if ( BPP(image->type) != 1 ) {
300         iclose(image);
301         PyErr_SetString(ImgfileError,
302                         "Can't handle imgfiles with bpp!=1");
303         return NULL;
304     }
305     xsize = image->xsize;
306     ysize = image->ysize;
307     zsize = image->zsize;
308     if ( zsize != 1 && zsize != 3) {
309         iclose(image);
310         PyErr_SetString(ImgfileError,
311                         "Can only handle 1 or 3 byte pixels");
312         return NULL;
313     }
314     if ( xsize > 8192 ) {
315         iclose(image);
316         PyErr_SetString(ImgfileError,
317                         "Can't handle image with > 8192 columns");
318         return NULL;
319     }
320 
321     if ( zsize == 3 ) zsize = 4;
322     rv = PyString_FromStringAndSize(NULL, xwtd*ywtd*zsize);
323     if ( rv == NULL ) {
324         iclose(image);
325         return NULL;
326     }
327     PyFPE_START_PROTECT("readscaled", return 0)
328     xfac = (float)xsize/(float)xwtd;
329     yfac = (float)ysize/(float)ywtd;
330     PyFPE_END_PROTECT(yfac)
331     cdatap = PyString_AsString(rv);
332     idatap = (long *)cdatap;
333 
334     if ( extended ) {
335         xscale(image, xsize, ysize, zsize,
336                idatap, xwtd, ywtd, fmode, blur);
337     } else {
338         if (top_to_bottom) {
339             yfirst = ywtd-1;
340             ylast = -1;
341             ystep = -1;
342         } else {
343             yfirst = 0;
344             ylast = ywtd;
345             ystep = 1;
346         }
347         for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
348             yorig = (int)(y*yfac);
349             if ( zsize == 1 ) {
350                 getrow(image, rs, yorig, 0);
351                 for(x=0; x<xwtd; x++ ) {
352                     *cdatap++ = rs[(int)(x*xfac)];
353                 }
354             } else {
355                 getrow(image, rs, yorig, 0);
356                 getrow(image, gs, yorig, 1);
357                 getrow(image, bs, yorig, 2);
358                 for(x=0; x<xwtd; x++ ) {
359                     xorig = (int)(x*xfac);
360                     *idatap++ = (rs[xorig] & 0xff)  |
361                         ((gs[xorig] & 0xff)<<8) |
362                         ((bs[xorig] & 0xff)<<16);
363                 }
364             }
365         }
366     }
367     iclose(image);
368     if ( error_called ) {
369         Py_DECREF(rv);
370         return NULL;
371     }
372     return rv;
373 }
374 
375 static PyObject *
imgfile_getsizes(PyObject * self,PyObject * args)376 imgfile_getsizes(PyObject *self, PyObject *args)
377 {
378     char *fname;
379     PyObject *rv;
380     IMAGE *image;
381 
382     if ( !PyArg_ParseTuple(args, "s:getsizes", &fname) )
383         return NULL;
384 
385     if ( (image = imgfile_open(fname)) == NULL )
386         return NULL;
387     rv = Py_BuildValue("(iii)", image->xsize, image->ysize, image->zsize);
388     iclose(image);
389     return rv;
390 }
391 
392 static PyObject *
imgfile_write(PyObject * self,PyObject * args)393 imgfile_write(PyObject *self, PyObject *args)
394 {
395     IMAGE *image;
396     char *fname;
397     int xsize, ysize, zsize, len;
398     char *cdatap;
399     long *idatap;
400     short rs[8192], gs[8192], bs[8192];
401     short r, g, b;
402     long rgb;
403     int x, y;
404     int yfirst, ylast, ystep;
405 
406 
407     if ( !PyArg_ParseTuple(args, "ss#iii:write",
408                       &fname, &cdatap, &len, &xsize, &ysize, &zsize) )
409         return NULL;
410 
411     if ( zsize != 1 && zsize != 3 ) {
412         PyErr_SetString(ImgfileError,
413                         "Can only handle 1 or 3 byte pixels");
414         return NULL;
415     }
416     if ( len != xsize * ysize * (zsize == 1 ? 1 : 4) ) {
417         PyErr_SetString(ImgfileError, "Data does not match sizes");
418         return NULL;
419     }
420     if ( xsize > 8192 ) {
421         PyErr_SetString(ImgfileError,
422                         "Can't handle image with > 8192 columns");
423         return NULL;
424     }
425 
426     error_called = 0;
427     errno = 0;
428     image =iopen(fname, "w", RLE(1), 3, xsize, ysize, zsize);
429     if ( image == 0 ) {
430         if ( ! error_called ) {
431             if (errno)
432                 PyErr_SetFromErrno(ImgfileError);
433             else
434                 PyErr_SetString(ImgfileError,
435                                 "Can't create image file");
436         }
437         return NULL;
438     }
439 
440     idatap = (long *)cdatap;
441 
442     if (top_to_bottom) {
443         yfirst = ysize-1;
444         ylast = -1;
445         ystep = -1;
446     } else {
447         yfirst = 0;
448         ylast = ysize;
449         ystep = 1;
450     }
451     for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
452         if ( zsize == 1 ) {
453             for( x=0; x<xsize; x++ )
454                 rs[x] = *cdatap++;
455             putrow(image, rs, y, 0);
456         } else {
457             for( x=0; x<xsize; x++ ) {
458                 rgb = *idatap++;
459                 r = rgb & 0xff;
460                 g = (rgb >> 8 ) & 0xff;
461                 b = (rgb >> 16 ) & 0xff;
462                 rs[x] = r;
463                 gs[x] = g;
464                 bs[x] = b;
465             }
466             putrow(image, rs, y, 0);
467             putrow(image, gs, y, 1);
468             putrow(image, bs, y, 2);
469         }
470     }
471     iclose(image);
472     if ( error_called )
473         return NULL;
474     Py_INCREF(Py_None);
475     return Py_None;
476 
477 }
478 
479 
480 static PyMethodDef imgfile_methods[] = {
481     { "getsizes",       imgfile_getsizes, METH_VARARGS },
482     { "read",           imgfile_read, METH_VARARGS },
483     { "readscaled",     imgfile_readscaled, METH_VARARGS},
484     { "write",          imgfile_write, METH_VARARGS },
485     { "ttob",           imgfile_ttob, METH_VARARGS },
486     { NULL,             NULL } /* Sentinel */
487 };
488 
489 
490 void
initimgfile(void)491 initimgfile(void)
492 {
493     PyObject *m, *d;
494 
495     if (PyErr_WarnPy3k("the imgfile module has been removed in "
496                        "Python 3.0", 2) < 0)
497         return;
498 
499     m = Py_InitModule("imgfile", imgfile_methods);
500     if (m == NULL)
501         return;
502     d = PyModule_GetDict(m);
503     ImgfileError = PyErr_NewException("imgfile.error", NULL, NULL);
504     if (ImgfileError != NULL)
505         PyDict_SetItemString(d, "error", ImgfileError);
506 }
507 
508 
509 
510