/Modules/imageop.c

http://unladen-swallow.googlecode.com/ · C · 794 lines · 663 code · 95 blank · 36 comment · 191 complexity · 573179c5071e8f44f6d548913925e645 MD5 · raw file

  1. /* imageopmodule - Various operations on pictures */
  2. #ifdef sun
  3. #define signed
  4. #endif
  5. #include "Python.h"
  6. #if SIZEOF_INT == 4
  7. typedef int Py_Int32;
  8. typedef unsigned int Py_UInt32;
  9. #else
  10. #if SIZEOF_LONG == 4
  11. typedef long Py_Int32;
  12. typedef unsigned long Py_UInt32;
  13. #else
  14. #error "No 4-byte integral type"
  15. #endif
  16. #endif
  17. #define CHARP(cp, xmax, x, y) ((char *)(cp+y*xmax+x))
  18. #define SHORTP(cp, xmax, x, y) ((short *)(cp+2*(y*xmax+x)))
  19. #define LONGP(cp, xmax, x, y) ((Py_Int32 *)(cp+4*(y*xmax+x)))
  20. static PyObject *ImageopError;
  21. static PyObject *ImageopDict;
  22. /**
  23. * Check a coordonnate, make sure that (0 < value).
  24. * Return 0 on error.
  25. */
  26. static int
  27. check_coordonnate(int value, const char* name)
  28. {
  29. if ( 0 < value)
  30. return 1;
  31. PyErr_Format(PyExc_ValueError, "%s value is negative or nul", name);
  32. return 0;
  33. }
  34. /**
  35. * Check integer overflow to make sure that product == x*y*size.
  36. * Return 0 on error.
  37. */
  38. static int
  39. check_multiply_size(int product, int x, const char* xname, int y, const char* yname, int size)
  40. {
  41. if ( !check_coordonnate(x, xname) )
  42. return 0;
  43. if ( !check_coordonnate(y, yname) )
  44. return 0;
  45. if ( size == (product / y) / x )
  46. return 1;
  47. PyErr_SetString(ImageopError, "String has incorrect length");
  48. return 0;
  49. }
  50. /**
  51. * Check integer overflow to make sure that product == x*y.
  52. * Return 0 on error.
  53. */
  54. static int
  55. check_multiply(int product, int x, int y)
  56. {
  57. return check_multiply_size(product, x, "x", y, "y", 1);
  58. }
  59. /* If this function returns true (the default if anything goes wrong), we're
  60. behaving in a backward-compatible way with respect to how multi-byte pixels
  61. are stored in the strings. The code in this module was originally written
  62. for an SGI which is a big-endian system, and so the old code assumed that
  63. 4-byte integers hold the R, G, and B values in a particular order.
  64. However, on little-endian systems the order is reversed, and so not
  65. actually compatible with what gl.lrectwrite and imgfile expect.
  66. (gl.lrectwrite and imgfile are also SGI-specific, however, it is
  67. conceivable that the data handled here comes from or goes to an SGI or that
  68. it is otherwise used in the expectation that the byte order in the strings
  69. is as specified.)
  70. The function returns the value of the module variable
  71. "backward_compatible", or 1 if the variable does not exist or is not an
  72. int.
  73. */
  74. static int
  75. imageop_backward_compatible(void)
  76. {
  77. static PyObject *bcos;
  78. PyObject *bco;
  79. long rc;
  80. if (ImageopDict == NULL) /* "cannot happen" */
  81. return 1;
  82. if (bcos == NULL) {
  83. /* cache string object for future use */
  84. bcos = PyString_FromString("backward_compatible");
  85. if (bcos == NULL)
  86. return 1;
  87. }
  88. bco = PyDict_GetItem(ImageopDict, bcos);
  89. if (bco == NULL)
  90. return 1;
  91. if (!PyInt_Check(bco))
  92. return 1;
  93. rc = PyInt_AsLong(bco);
  94. if (PyErr_Occurred()) {
  95. /* not an integer, or too large, or something */
  96. PyErr_Clear();
  97. rc = 1;
  98. }
  99. return rc != 0; /* convert to values 0, 1 */
  100. }
  101. static PyObject *
  102. imageop_crop(PyObject *self, PyObject *args)
  103. {
  104. char *cp, *ncp;
  105. short *nsp;
  106. Py_Int32 *nlp;
  107. int len, size, x, y, newx1, newx2, newy1, newy2, nlen;
  108. int ix, iy, xstep, ystep;
  109. PyObject *rv;
  110. if ( !PyArg_ParseTuple(args, "s#iiiiiii", &cp, &len, &size, &x, &y,
  111. &newx1, &newy1, &newx2, &newy2) )
  112. return 0;
  113. if ( size != 1 && size != 2 && size != 4 ) {
  114. PyErr_SetString(ImageopError, "Size should be 1, 2 or 4");
  115. return 0;
  116. }
  117. if ( !check_multiply_size(len, x, "x", y, "y", size) )
  118. return 0;
  119. xstep = (newx1 < newx2)? 1 : -1;
  120. ystep = (newy1 < newy2)? 1 : -1;
  121. nlen = (abs(newx2-newx1)+1)*(abs(newy2-newy1)+1)*size;
  122. if ( !check_multiply_size(nlen, abs(newx2-newx1)+1, "abs(newx2-newx1)+1", abs(newy2-newy1)+1, "abs(newy2-newy1)+1", size) )
  123. return 0;
  124. rv = PyString_FromStringAndSize(NULL, nlen);
  125. if ( rv == 0 )
  126. return 0;
  127. ncp = (char *)PyString_AsString(rv);
  128. nsp = (short *)ncp;
  129. nlp = (Py_Int32 *)ncp;
  130. newy2 += ystep;
  131. newx2 += xstep;
  132. for( iy = newy1; iy != newy2; iy+=ystep ) {
  133. for ( ix = newx1; ix != newx2; ix+=xstep ) {
  134. if ( iy < 0 || iy >= y || ix < 0 || ix >= x ) {
  135. if ( size == 1 )
  136. *ncp++ = 0;
  137. else
  138. *nlp++ = 0;
  139. } else {
  140. if ( size == 1 )
  141. *ncp++ = *CHARP(cp, x, ix, iy);
  142. else if ( size == 2 )
  143. *nsp++ = *SHORTP(cp, x, ix, iy);
  144. else
  145. *nlp++ = *LONGP(cp, x, ix, iy);
  146. }
  147. }
  148. }
  149. return rv;
  150. }
  151. static PyObject *
  152. imageop_scale(PyObject *self, PyObject *args)
  153. {
  154. char *cp, *ncp;
  155. short *nsp;
  156. Py_Int32 *nlp;
  157. int len, size, x, y, newx, newy, nlen;
  158. int ix, iy;
  159. int oix, oiy;
  160. PyObject *rv;
  161. if ( !PyArg_ParseTuple(args, "s#iiiii",
  162. &cp, &len, &size, &x, &y, &newx, &newy) )
  163. return 0;
  164. if ( size != 1 && size != 2 && size != 4 ) {
  165. PyErr_SetString(ImageopError, "Size should be 1, 2 or 4");
  166. return 0;
  167. }
  168. if ( !check_multiply_size(len, x, "x", y, "y", size) )
  169. return 0;
  170. nlen = newx*newy*size;
  171. if ( !check_multiply_size(nlen, newx, "newx", newy, "newy", size) )
  172. return 0;
  173. rv = PyString_FromStringAndSize(NULL, nlen);
  174. if ( rv == 0 )
  175. return 0;
  176. ncp = (char *)PyString_AsString(rv);
  177. nsp = (short *)ncp;
  178. nlp = (Py_Int32 *)ncp;
  179. for( iy = 0; iy < newy; iy++ ) {
  180. for ( ix = 0; ix < newx; ix++ ) {
  181. oix = ix * x / newx;
  182. oiy = iy * y / newy;
  183. if ( size == 1 )
  184. *ncp++ = *CHARP(cp, x, oix, oiy);
  185. else if ( size == 2 )
  186. *nsp++ = *SHORTP(cp, x, oix, oiy);
  187. else
  188. *nlp++ = *LONGP(cp, x, oix, oiy);
  189. }
  190. }
  191. return rv;
  192. }
  193. /* Note: this routine can use a bit of optimizing */
  194. static PyObject *
  195. imageop_tovideo(PyObject *self, PyObject *args)
  196. {
  197. int maxx, maxy, x, y, len;
  198. int i;
  199. unsigned char *cp, *ncp;
  200. int width;
  201. PyObject *rv;
  202. if ( !PyArg_ParseTuple(args, "s#iii", &cp, &len, &width, &maxx, &maxy) )
  203. return 0;
  204. if ( width != 1 && width != 4 ) {
  205. PyErr_SetString(ImageopError, "Size should be 1 or 4");
  206. return 0;
  207. }
  208. if ( !check_multiply_size(len, maxx, "max", maxy, "maxy", width) )
  209. return 0;
  210. rv = PyString_FromStringAndSize(NULL, len);
  211. if ( rv == 0 )
  212. return 0;
  213. ncp = (unsigned char *)PyString_AsString(rv);
  214. if ( width == 1 ) {
  215. memcpy(ncp, cp, maxx); /* Copy first line */
  216. ncp += maxx;
  217. for (y=1; y<maxy; y++) { /* Interpolate other lines */
  218. for(x=0; x<maxx; x++) {
  219. i = y*maxx + x;
  220. *ncp++ = ((int)cp[i] + (int)cp[i-maxx]) >> 1;
  221. }
  222. }
  223. } else {
  224. memcpy(ncp, cp, maxx*4); /* Copy first line */
  225. ncp += maxx*4;
  226. for (y=1; y<maxy; y++) { /* Interpolate other lines */
  227. for(x=0; x<maxx; x++) {
  228. i = (y*maxx + x)*4 + 1;
  229. *ncp++ = 0; /* Skip alfa comp */
  230. *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
  231. i++;
  232. *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
  233. i++;
  234. *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
  235. }
  236. }
  237. }
  238. return rv;
  239. }
  240. static PyObject *
  241. imageop_grey2mono(PyObject *self, PyObject *args)
  242. {
  243. int tres, x, y, len;
  244. unsigned char *cp, *ncp;
  245. unsigned char ovalue;
  246. PyObject *rv;
  247. int i, bit;
  248. if ( !PyArg_ParseTuple(args, "s#iii", &cp, &len, &x, &y, &tres) )
  249. return 0;
  250. if ( !check_multiply(len, x, y) )
  251. return 0;
  252. rv = PyString_FromStringAndSize(NULL, (len+7)/8);
  253. if ( rv == 0 )
  254. return 0;
  255. ncp = (unsigned char *)PyString_AsString(rv);
  256. bit = 0x80;
  257. ovalue = 0;
  258. for ( i=0; i < len; i++ ) {
  259. if ( (int)cp[i] > tres )
  260. ovalue |= bit;
  261. bit >>= 1;
  262. if ( bit == 0 ) {
  263. *ncp++ = ovalue;
  264. bit = 0x80;
  265. ovalue = 0;
  266. }
  267. }
  268. if ( bit != 0x80 )
  269. *ncp++ = ovalue;
  270. return rv;
  271. }
  272. static PyObject *
  273. imageop_grey2grey4(PyObject *self, PyObject *args)
  274. {
  275. int x, y, len;
  276. unsigned char *cp, *ncp;
  277. unsigned char ovalue;
  278. PyObject *rv;
  279. int i;
  280. int pos;
  281. if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
  282. return 0;
  283. if ( !check_multiply(len, x, y) )
  284. return 0;
  285. rv = PyString_FromStringAndSize(NULL, (len+1)/2);
  286. if ( rv == 0 )
  287. return 0;
  288. ncp = (unsigned char *)PyString_AsString(rv);
  289. pos = 0;
  290. ovalue = 0;
  291. for ( i=0; i < len; i++ ) {
  292. ovalue |= ((int)cp[i] & 0xf0) >> pos;
  293. pos += 4;
  294. if ( pos == 8 ) {
  295. *ncp++ = ovalue;
  296. ovalue = 0;
  297. pos = 0;
  298. }
  299. }
  300. if ( pos != 0 )
  301. *ncp++ = ovalue;
  302. return rv;
  303. }
  304. static PyObject *
  305. imageop_grey2grey2(PyObject *self, PyObject *args)
  306. {
  307. int x, y, len;
  308. unsigned char *cp, *ncp;
  309. unsigned char ovalue;
  310. PyObject *rv;
  311. int i;
  312. int pos;
  313. if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
  314. return 0;
  315. if ( !check_multiply(len, x, y) )
  316. return 0;
  317. rv = PyString_FromStringAndSize(NULL, (len+3)/4);
  318. if ( rv == 0 )
  319. return 0;
  320. ncp = (unsigned char *)PyString_AsString(rv);
  321. pos = 0;
  322. ovalue = 0;
  323. for ( i=0; i < len; i++ ) {
  324. ovalue |= ((int)cp[i] & 0xc0) >> pos;
  325. pos += 2;
  326. if ( pos == 8 ) {
  327. *ncp++ = ovalue;
  328. ovalue = 0;
  329. pos = 0;
  330. }
  331. }
  332. if ( pos != 0 )
  333. *ncp++ = ovalue;
  334. return rv;
  335. }
  336. static PyObject *
  337. imageop_dither2mono(PyObject *self, PyObject *args)
  338. {
  339. int sum, x, y, len;
  340. unsigned char *cp, *ncp;
  341. unsigned char ovalue;
  342. PyObject *rv;
  343. int i, bit;
  344. if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
  345. return 0;
  346. if ( !check_multiply(len, x, y) )
  347. return 0;
  348. rv = PyString_FromStringAndSize(NULL, (len+7)/8);
  349. if ( rv == 0 )
  350. return 0;
  351. ncp = (unsigned char *)PyString_AsString(rv);
  352. bit = 0x80;
  353. ovalue = 0;
  354. sum = 0;
  355. for ( i=0; i < len; i++ ) {
  356. sum += cp[i];
  357. if ( sum >= 256 ) {
  358. sum -= 256;
  359. ovalue |= bit;
  360. }
  361. bit >>= 1;
  362. if ( bit == 0 ) {
  363. *ncp++ = ovalue;
  364. bit = 0x80;
  365. ovalue = 0;
  366. }
  367. }
  368. if ( bit != 0x80 )
  369. *ncp++ = ovalue;
  370. return rv;
  371. }
  372. static PyObject *
  373. imageop_dither2grey2(PyObject *self, PyObject *args)
  374. {
  375. int x, y, len;
  376. unsigned char *cp, *ncp;
  377. unsigned char ovalue;
  378. PyObject *rv;
  379. int i;
  380. int pos;
  381. int sum = 0, nvalue;
  382. if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
  383. return 0;
  384. if ( !check_multiply(len, x, y) )
  385. return 0;
  386. rv = PyString_FromStringAndSize(NULL, (len+3)/4);
  387. if ( rv == 0 )
  388. return 0;
  389. ncp = (unsigned char *)PyString_AsString(rv);
  390. pos = 1;
  391. ovalue = 0;
  392. for ( i=0; i < len; i++ ) {
  393. sum += cp[i];
  394. nvalue = sum & 0x180;
  395. sum -= nvalue;
  396. ovalue |= nvalue >> pos;
  397. pos += 2;
  398. if ( pos == 9 ) {
  399. *ncp++ = ovalue;
  400. ovalue = 0;
  401. pos = 1;
  402. }
  403. }
  404. if ( pos != 0 )
  405. *ncp++ = ovalue;
  406. return rv;
  407. }
  408. static PyObject *
  409. imageop_mono2grey(PyObject *self, PyObject *args)
  410. {
  411. int v0, v1, x, y, len, nlen;
  412. unsigned char *cp, *ncp;
  413. PyObject *rv;
  414. int i, bit;
  415. if ( !PyArg_ParseTuple(args, "s#iiii", &cp, &len, &x, &y, &v0, &v1) )
  416. return 0;
  417. nlen = x*y;
  418. if ( !check_multiply(nlen, x, y) )
  419. return 0;
  420. if ( (nlen+7)/8 != len ) {
  421. PyErr_SetString(ImageopError, "String has incorrect length");
  422. return 0;
  423. }
  424. rv = PyString_FromStringAndSize(NULL, nlen);
  425. if ( rv == 0 )
  426. return 0;
  427. ncp = (unsigned char *)PyString_AsString(rv);
  428. bit = 0x80;
  429. for ( i=0; i < nlen; i++ ) {
  430. if ( *cp & bit )
  431. *ncp++ = v1;
  432. else
  433. *ncp++ = v0;
  434. bit >>= 1;
  435. if ( bit == 0 ) {
  436. bit = 0x80;
  437. cp++;
  438. }
  439. }
  440. return rv;
  441. }
  442. static PyObject *
  443. imageop_grey22grey(PyObject *self, PyObject *args)
  444. {
  445. int x, y, len, nlen;
  446. unsigned char *cp, *ncp;
  447. PyObject *rv;
  448. int i, pos, value = 0, nvalue;
  449. if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
  450. return 0;
  451. nlen = x*y;
  452. if ( !check_multiply(nlen, x, y) ) {
  453. return 0;
  454. }
  455. if ( (nlen+3)/4 != len ) {
  456. PyErr_SetString(ImageopError, "String has incorrect length");
  457. return 0;
  458. }
  459. rv = PyString_FromStringAndSize(NULL, nlen);
  460. if ( rv == 0 )
  461. return 0;
  462. ncp = (unsigned char *)PyString_AsString(rv);
  463. pos = 0;
  464. for ( i=0; i < nlen; i++ ) {
  465. if ( pos == 0 ) {
  466. value = *cp++;
  467. pos = 8;
  468. }
  469. pos -= 2;
  470. nvalue = (value >> pos) & 0x03;
  471. *ncp++ = nvalue | (nvalue << 2) |
  472. (nvalue << 4) | (nvalue << 6);
  473. }
  474. return rv;
  475. }
  476. static PyObject *
  477. imageop_grey42grey(PyObject *self, PyObject *args)
  478. {
  479. int x, y, len, nlen;
  480. unsigned char *cp, *ncp;
  481. PyObject *rv;
  482. int i, pos, value = 0, nvalue;
  483. if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
  484. return 0;
  485. nlen = x*y;
  486. if ( !check_multiply(nlen, x, y) )
  487. return 0;
  488. if ( (nlen+1)/2 != len ) {
  489. PyErr_SetString(ImageopError, "String has incorrect length");
  490. return 0;
  491. }
  492. rv = PyString_FromStringAndSize(NULL, nlen);
  493. if ( rv == 0 )
  494. return 0;
  495. ncp = (unsigned char *)PyString_AsString(rv);
  496. pos = 0;
  497. for ( i=0; i < nlen; i++ ) {
  498. if ( pos == 0 ) {
  499. value = *cp++;
  500. pos = 8;
  501. }
  502. pos -= 4;
  503. nvalue = (value >> pos) & 0x0f;
  504. *ncp++ = nvalue | (nvalue << 4);
  505. }
  506. return rv;
  507. }
  508. static PyObject *
  509. imageop_rgb2rgb8(PyObject *self, PyObject *args)
  510. {
  511. int x, y, len, nlen;
  512. unsigned char *cp;
  513. unsigned char *ncp;
  514. PyObject *rv;
  515. int i, r, g, b;
  516. int backward_compatible = imageop_backward_compatible();
  517. if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
  518. return 0;
  519. if ( !check_multiply_size(len, x, "x", y, "y", 4) )
  520. return 0;
  521. nlen = x*y;
  522. if ( !check_multiply(nlen, x, y) )
  523. return 0;
  524. rv = PyString_FromStringAndSize(NULL, nlen);
  525. if ( rv == 0 )
  526. return 0;
  527. ncp = (unsigned char *)PyString_AsString(rv);
  528. for ( i=0; i < nlen; i++ ) {
  529. /* Bits in source: aaaaaaaa BBbbbbbb GGGggggg RRRrrrrr */
  530. if (backward_compatible) {
  531. Py_UInt32 value = * (Py_UInt32 *) cp;
  532. cp += 4;
  533. r = (int) ((value & 0xff) / 255. * 7. + .5);
  534. g = (int) (((value >> 8) & 0xff) / 255. * 7. + .5);
  535. b = (int) (((value >> 16) & 0xff) / 255. * 3. + .5);
  536. } else {
  537. cp++; /* skip alpha channel */
  538. b = (int) (*cp++ / 255. * 3. + .5);
  539. g = (int) (*cp++ / 255. * 7. + .5);
  540. r = (int) (*cp++ / 255. * 7. + .5);
  541. }
  542. *ncp++ = (unsigned char)((r<<5) | (b<<3) | g);
  543. }
  544. return rv;
  545. }
  546. static PyObject *
  547. imageop_rgb82rgb(PyObject *self, PyObject *args)
  548. {
  549. int x, y, len, nlen;
  550. unsigned char *cp;
  551. unsigned char *ncp;
  552. PyObject *rv;
  553. int i, r, g, b;
  554. unsigned char value;
  555. int backward_compatible = imageop_backward_compatible();
  556. if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
  557. return 0;
  558. if ( !check_multiply(len, x, y) )
  559. return 0;
  560. nlen = x*y*4;
  561. if ( !check_multiply_size(nlen, x, "x", y, "y", 4) )
  562. return 0;
  563. rv = PyString_FromStringAndSize(NULL, nlen);
  564. if ( rv == 0 )
  565. return 0;
  566. ncp = (unsigned char *)PyString_AsString(rv);
  567. for ( i=0; i < len; i++ ) {
  568. /* Bits in source: RRRBBGGG
  569. ** Red and Green are multiplied by 36.5, Blue by 85
  570. */
  571. value = *cp++;
  572. r = (value >> 5) & 7;
  573. g = (value ) & 7;
  574. b = (value >> 3) & 3;
  575. r = (r<<5) | (r<<3) | (r>>1);
  576. g = (g<<5) | (g<<3) | (g>>1);
  577. b = (b<<6) | (b<<4) | (b<<2) | b;
  578. if (backward_compatible) {
  579. Py_UInt32 nvalue = r | (g<<8) | (b<<16);
  580. * (Py_UInt32 *) ncp = nvalue;
  581. ncp += 4;
  582. } else {
  583. *ncp++ = 0;
  584. *ncp++ = b;
  585. *ncp++ = g;
  586. *ncp++ = r;
  587. }
  588. }
  589. return rv;
  590. }
  591. static PyObject *
  592. imageop_rgb2grey(PyObject *self, PyObject *args)
  593. {
  594. int x, y, len, nlen;
  595. unsigned char *cp;
  596. unsigned char *ncp;
  597. PyObject *rv;
  598. int i, r, g, b;
  599. int nvalue;
  600. int backward_compatible = imageop_backward_compatible();
  601. if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
  602. return 0;
  603. if ( !check_multiply_size(len, x, "x", y, "y", 4) )
  604. return 0;
  605. nlen = x*y;
  606. if ( !check_multiply(nlen, x, y) )
  607. return 0;
  608. rv = PyString_FromStringAndSize(NULL, nlen);
  609. if ( rv == 0 )
  610. return 0;
  611. ncp = (unsigned char *)PyString_AsString(rv);
  612. for ( i=0; i < nlen; i++ ) {
  613. if (backward_compatible) {
  614. Py_UInt32 value = * (Py_UInt32 *) cp;
  615. cp += 4;
  616. r = (int) ((value & 0xff) / 255. * 7. + .5);
  617. g = (int) (((value >> 8) & 0xff) / 255. * 7. + .5);
  618. b = (int) (((value >> 16) & 0xff) / 255. * 3. + .5);
  619. } else {
  620. cp++; /* skip alpha channel */
  621. b = *cp++;
  622. g = *cp++;
  623. r = *cp++;
  624. }
  625. nvalue = (int)(0.30*r + 0.59*g + 0.11*b);
  626. if ( nvalue > 255 ) nvalue = 255;
  627. *ncp++ = (unsigned char)nvalue;
  628. }
  629. return rv;
  630. }
  631. static PyObject *
  632. imageop_grey2rgb(PyObject *self, PyObject *args)
  633. {
  634. int x, y, len, nlen;
  635. unsigned char *cp;
  636. unsigned char *ncp;
  637. PyObject *rv;
  638. int i;
  639. unsigned char value;
  640. int backward_compatible = imageop_backward_compatible();
  641. if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
  642. return 0;
  643. if ( !check_multiply(len, x, y) )
  644. return 0;
  645. nlen = x*y*4;
  646. if ( !check_multiply_size(nlen, x, "x", y, "y", 4) )
  647. return 0;
  648. rv = PyString_FromStringAndSize(NULL, nlen);
  649. if ( rv == 0 )
  650. return 0;
  651. ncp = (unsigned char *)PyString_AsString(rv);
  652. for ( i=0; i < len; i++ ) {
  653. value = *cp++;
  654. if (backward_compatible) {
  655. * (Py_UInt32 *) ncp = (Py_UInt32) value | ((Py_UInt32) value << 8 ) | ((Py_UInt32) value << 16);
  656. ncp += 4;
  657. } else {
  658. *ncp++ = 0;
  659. *ncp++ = value;
  660. *ncp++ = value;
  661. *ncp++ = value;
  662. }
  663. }
  664. return rv;
  665. }
  666. static PyMethodDef imageop_methods[] = {
  667. { "crop", imageop_crop, METH_VARARGS },
  668. { "scale", imageop_scale, METH_VARARGS },
  669. { "grey2mono", imageop_grey2mono, METH_VARARGS },
  670. { "grey2grey2", imageop_grey2grey2, METH_VARARGS },
  671. { "grey2grey4", imageop_grey2grey4, METH_VARARGS },
  672. { "dither2mono", imageop_dither2mono, METH_VARARGS },
  673. { "dither2grey2", imageop_dither2grey2, METH_VARARGS },
  674. { "mono2grey", imageop_mono2grey, METH_VARARGS },
  675. { "grey22grey", imageop_grey22grey, METH_VARARGS },
  676. { "grey42grey", imageop_grey42grey, METH_VARARGS },
  677. { "tovideo", imageop_tovideo, METH_VARARGS },
  678. { "rgb2rgb8", imageop_rgb2rgb8, METH_VARARGS },
  679. { "rgb82rgb", imageop_rgb82rgb, METH_VARARGS },
  680. { "rgb2grey", imageop_rgb2grey, METH_VARARGS },
  681. { "grey2rgb", imageop_grey2rgb, METH_VARARGS },
  682. { 0, 0 }
  683. };
  684. PyMODINIT_FUNC
  685. initimageop(void)
  686. {
  687. PyObject *m;
  688. if (PyErr_WarnPy3k("the imageop module has been removed in "
  689. "Python 3.0", 2) < 0)
  690. return;
  691. m = Py_InitModule("imageop", imageop_methods);
  692. if (m == NULL)
  693. return;
  694. ImageopDict = PyModule_GetDict(m);
  695. ImageopError = PyErr_NewException("imageop.error", NULL, NULL);
  696. if (ImageopError != NULL)
  697. PyDict_SetItemString(ImageopDict, "error", ImageopError);
  698. }