/Modules/imgfile.c

http://unladen-swallow.googlecode.com/ · C · 509 lines · 424 code · 60 blank · 25 comment · 116 complexity · aad336c7c64883fd5df5ee07625feed8 MD5 · raw file

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