home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Programming / Python2 / Python20_source / Modules / imgfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-25  |  10.9 KB  |  515 lines

  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
  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 *
  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 *
  73. imgfile_ttob(PyObject *self, PyObject *args)
  74. {
  75.     int newval;
  76.     PyObject *rv;
  77.     
  78.     if (!PyArg_Parse(args, "i", &newval))
  79.         return NULL;
  80.     rv = PyInt_FromLong(top_to_bottom);
  81.     top_to_bottom = newval;
  82.     return rv;
  83. }
  84.  
  85. static PyObject *
  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_Parse(args, "s", &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
  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
  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
  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
  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
  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 *
  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.     int cnt;
  254.     IMAGE *image;
  255.     char *filter;
  256.     double blur;
  257.     int extended;
  258.     int fmode = 0;
  259.     int yfirst, ylast, ystep;
  260.  
  261.     /*
  262.     ** Parse args. Funny, since arg 4 and 5 are optional
  263.     ** (filter name and blur factor). Also, 4 or 5 arguments indicates
  264.     ** extended scale algorithm in stead of simple-minded pixel drop/dup.
  265.     */
  266.     extended = 0;
  267.     cnt = PyTuple_Size(args);
  268.     if ( cnt == 5 ) {
  269.         extended = 1;
  270.         if ( !PyArg_Parse(args, "(siisd)",
  271.                   &fname, &xwtd, &ywtd, &filter, &blur) )
  272.             return NULL;
  273.     } else if ( cnt == 4 ) {
  274.         extended = 1;
  275.         if ( !PyArg_Parse(args, "(siis)",
  276.                   &fname, &xwtd, &ywtd, &filter) )
  277.             return NULL;
  278.         blur = 1.0;
  279.     } else if ( !PyArg_Parse(args, "(sii)", &fname, &xwtd, &ywtd) )
  280.         return NULL;
  281.  
  282.     /*
  283.     ** Check parameters, open file and check type, rows, etc.
  284.     */
  285.     if ( extended ) {
  286.         if ( strcmp(filter, "impulse") == 0 )
  287.             fmode = IMPULSE;
  288.         else if ( strcmp( filter, "box") == 0 )
  289.             fmode = BOX;
  290.         else if ( strcmp( filter, "triangle") == 0 )
  291.             fmode = TRIANGLE;
  292.         else if ( strcmp( filter, "quadratic") == 0 )
  293.             fmode = QUADRATIC;
  294.         else if ( strcmp( filter, "gaussian") == 0 )
  295.             fmode = GAUSSIAN;
  296.         else {
  297.             PyErr_SetString(ImgfileError, "Unknown filter type");
  298.             return NULL;
  299.         }
  300.     }
  301.     
  302.     if ( (image = imgfile_open(fname)) == NULL )
  303.         return NULL;
  304.     
  305.     if ( image->colormap != CM_NORMAL ) {
  306.         iclose(image);
  307.         PyErr_SetString(ImgfileError,
  308.                 "Can only handle CM_NORMAL images");
  309.         return NULL;
  310.     }
  311.     if ( BPP(image->type) != 1 ) {
  312.         iclose(image);
  313.         PyErr_SetString(ImgfileError,
  314.                 "Can't handle imgfiles with bpp!=1");
  315.         return NULL;
  316.     }
  317.     xsize = image->xsize;
  318.     ysize = image->ysize;
  319.     zsize = image->zsize;
  320.     if ( zsize != 1 && zsize != 3) {
  321.         iclose(image);
  322.         PyErr_SetString(ImgfileError,
  323.                 "Can only handle 1 or 3 byte pixels");
  324.         return NULL;
  325.     }
  326.     if ( xsize > 8192 ) {
  327.         iclose(image);
  328.         PyErr_SetString(ImgfileError,
  329.                 "Can't handle image with > 8192 columns");
  330.         return NULL;
  331.     }
  332.  
  333.     if ( zsize == 3 ) zsize = 4;
  334.     rv = PyString_FromStringAndSize(NULL, xwtd*ywtd*zsize);
  335.     if ( rv == NULL ) {
  336.         iclose(image);
  337.         return NULL;
  338.     }
  339.     PyFPE_START_PROTECT("readscaled", return 0)
  340.     xfac = (float)xsize/(float)xwtd;
  341.     yfac = (float)ysize/(float)ywtd;
  342.     PyFPE_END_PROTECT(yfac)
  343.     cdatap = PyString_AsString(rv);
  344.     idatap = (long *)cdatap;
  345.  
  346.     if ( extended ) {
  347.         xscale(image, xsize, ysize, zsize,
  348.                idatap, xwtd, ywtd, fmode, blur);
  349.     } else {
  350.         if (top_to_bottom) {
  351.             yfirst = ywtd-1;
  352.             ylast = -1;
  353.             ystep = -1;
  354.         } else {
  355.             yfirst = 0;
  356.             ylast = ywtd;
  357.             ystep = 1;
  358.         }
  359.         for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
  360.             yorig = (int)(y*yfac);
  361.             if ( zsize == 1 ) {
  362.                 getrow(image, rs, yorig, 0);
  363.                 for(x=0; x<xwtd; x++ ) {
  364.                     *cdatap++ = rs[(int)(x*xfac)];    
  365.                 }
  366.             } else {
  367.                 getrow(image, rs, yorig, 0);
  368.                 getrow(image, gs, yorig, 1);
  369.                 getrow(image, bs, yorig, 2);
  370.                 for(x=0; x<xwtd; x++ ) {
  371.                     xorig = (int)(x*xfac);
  372.                     *idatap++ = (rs[xorig] & 0xff)  |
  373.                         ((gs[xorig] & 0xff)<<8) |
  374.                         ((bs[xorig] & 0xff)<<16);
  375.                 }
  376.             }
  377.         }
  378.     }
  379.     iclose(image);
  380.     if ( error_called ) {
  381.         Py_DECREF(rv);
  382.         return NULL;
  383.     }
  384.     return rv;
  385. }
  386.  
  387. static PyObject *
  388. imgfile_getsizes(PyObject *self, PyObject *args)
  389. {
  390.     char *fname;
  391.     PyObject *rv;
  392.     IMAGE *image;
  393.     
  394.     if ( !PyArg_Parse(args, "s", &fname) )
  395.         return NULL;
  396.     
  397.     if ( (image = imgfile_open(fname)) == NULL )
  398.         return NULL;
  399.     rv = Py_BuildValue("(iii)", image->xsize, image->ysize, image->zsize);
  400.     iclose(image);
  401.     return rv;
  402. }
  403.  
  404. static PyObject *
  405. imgfile_write(PyObject *self, PyObject *args)
  406. {
  407.     IMAGE *image;
  408.     char *fname;
  409.     int xsize, ysize, zsize, len;
  410.     char *cdatap;
  411.     long *idatap;
  412.     short rs[8192], gs[8192], bs[8192];
  413.     short r, g, b;
  414.     long rgb;
  415.     int x, y;
  416.     int yfirst, ylast, ystep;
  417.  
  418.  
  419.     if ( !PyArg_Parse(args, "(ss#iii)",
  420.               &fname, &cdatap, &len, &xsize, &ysize, &zsize) )
  421.         return NULL;
  422.     
  423.     if ( zsize != 1 && zsize != 3 ) {
  424.         PyErr_SetString(ImgfileError,
  425.                 "Can only handle 1 or 3 byte pixels");
  426.         return NULL;
  427.     }
  428.     if ( len != xsize * ysize * (zsize == 1 ? 1 : 4) ) {
  429.         PyErr_SetString(ImgfileError, "Data does not match sizes");
  430.         return NULL;
  431.     }
  432.     if ( xsize > 8192 ) {
  433.         PyErr_SetString(ImgfileError,
  434.                 "Can't handle image with > 8192 columns");
  435.         return NULL;
  436.     }
  437.  
  438.     error_called = 0;
  439.     errno = 0;
  440.     image =iopen(fname, "w", RLE(1), 3, xsize, ysize, zsize);
  441.     if ( image == 0 ) {
  442.         if ( ! error_called ) {
  443.             if (errno)
  444.                 PyErr_SetFromErrno(ImgfileError);
  445.             else
  446.                 PyErr_SetString(ImgfileError,
  447.                         "Can't create image file");
  448.         }
  449.         return NULL;
  450.     }
  451.  
  452.     idatap = (long *)cdatap;
  453.     
  454.     if (top_to_bottom) {
  455.         yfirst = ysize-1;
  456.         ylast = -1;
  457.         ystep = -1;
  458.     } else {
  459.         yfirst = 0;
  460.         ylast = ysize;
  461.         ystep = 1;
  462.     }
  463.     for ( y=yfirst; y != ylast && !error_called; y += ystep ) {
  464.         if ( zsize == 1 ) {
  465.             for( x=0; x<xsize; x++ )
  466.                 rs[x] = *cdatap++;
  467.             putrow(image, rs, y, 0);
  468.         } else {
  469.             for( x=0; x<xsize; x++ ) {
  470.                 rgb = *idatap++;
  471.                 r = rgb & 0xff;
  472.                 g = (rgb >> 8 ) & 0xff;
  473.                 b = (rgb >> 16 ) & 0xff;
  474.                 rs[x] = r;
  475.                 gs[x] = g;
  476.                 bs[x] = b;
  477.             }
  478.             putrow(image, rs, y, 0);
  479.             putrow(image, gs, y, 1);
  480.             putrow(image, bs, y, 2);
  481.         }
  482.     }
  483.     iclose(image);
  484.     if ( error_called )
  485.         return NULL;
  486.     Py_INCREF(Py_None);
  487.     return Py_None;
  488.     
  489. }
  490.  
  491.  
  492. static PyMethodDef imgfile_methods[] = {
  493.     { "getsizes",    imgfile_getsizes },
  494.     { "read",    imgfile_read },
  495.     { "readscaled",    imgfile_readscaled, 1},
  496.     { "write",    imgfile_write },
  497.     { "ttob",    imgfile_ttob },
  498.     { NULL,        NULL } /* Sentinel */
  499. };
  500.  
  501.  
  502. void
  503. initimgfile(void)
  504. {
  505.     PyObject *m, *d;
  506.     m = Py_InitModule("imgfile", imgfile_methods);
  507.     d = PyModule_GetDict(m);
  508.     ImgfileError = PyErr_NewException("imgfile.error", NULL, NULL);
  509.     if (ImgfileError != NULL)
  510.         PyDict_SetItemString(d, "error", ImgfileError);
  511. }
  512.  
  513.  
  514.  
  515.