Manual py3k backport: [svn r74158] Issue #6218: Make io.BytesIO and io.StringIO pickl...
[python.git] / Modules / imageop.c
blob8d0d68f71dc2f2878e7aca5dc04f3f7f370926c3
2 /* imageopmodule - Various operations on pictures */
4 #ifdef sun
5 #define signed
6 #endif
8 #include "Python.h"
10 #if SIZEOF_INT == 4
11 typedef int Py_Int32;
12 typedef unsigned int Py_UInt32;
13 #else
14 #if SIZEOF_LONG == 4
15 typedef long Py_Int32;
16 typedef unsigned long Py_UInt32;
17 #else
18 #error "No 4-byte integral type"
19 #endif
20 #endif
22 #define CHARP(cp, xmax, x, y) ((char *)(cp+y*xmax+x))
23 #define SHORTP(cp, xmax, x, y) ((short *)(cp+2*(y*xmax+x)))
24 #define LONGP(cp, xmax, x, y) ((Py_Int32 *)(cp+4*(y*xmax+x)))
26 static PyObject *ImageopError;
27 static PyObject *ImageopDict;
29 /**
30 * Check a coordonnate, make sure that (0 < value).
31 * Return 0 on error.
33 static int
34 check_coordonnate(int value, const char* name)
36 if ( 0 < value)
37 return 1;
38 PyErr_Format(PyExc_ValueError, "%s value is negative or nul", name);
39 return 0;
42 /**
43 * Check integer overflow to make sure that product == x*y*size.
44 * Return 0 on error.
46 static int
47 check_multiply_size(int product, int x, const char* xname, int y, const char* yname, int size)
49 if ( !check_coordonnate(x, xname) )
50 return 0;
51 if ( !check_coordonnate(y, yname) )
52 return 0;
53 if ( size == (product / y) / x )
54 return 1;
55 PyErr_SetString(ImageopError, "String has incorrect length");
56 return 0;
59 /**
60 * Check integer overflow to make sure that product == x*y.
61 * Return 0 on error.
63 static int
64 check_multiply(int product, int x, int y)
66 return check_multiply_size(product, x, "x", y, "y", 1);
69 /* If this function returns true (the default if anything goes wrong), we're
70 behaving in a backward-compatible way with respect to how multi-byte pixels
71 are stored in the strings. The code in this module was originally written
72 for an SGI which is a big-endian system, and so the old code assumed that
73 4-byte integers hold the R, G, and B values in a particular order.
74 However, on little-endian systems the order is reversed, and so not
75 actually compatible with what gl.lrectwrite and imgfile expect.
76 (gl.lrectwrite and imgfile are also SGI-specific, however, it is
77 conceivable that the data handled here comes from or goes to an SGI or that
78 it is otherwise used in the expectation that the byte order in the strings
79 is as specified.)
81 The function returns the value of the module variable
82 "backward_compatible", or 1 if the variable does not exist or is not an
83 int.
86 static int
87 imageop_backward_compatible(void)
89 static PyObject *bcos;
90 PyObject *bco;
91 long rc;
93 if (ImageopDict == NULL) /* "cannot happen" */
94 return 1;
95 if (bcos == NULL) {
96 /* cache string object for future use */
97 bcos = PyString_FromString("backward_compatible");
98 if (bcos == NULL)
99 return 1;
101 bco = PyDict_GetItem(ImageopDict, bcos);
102 if (bco == NULL)
103 return 1;
104 if (!PyInt_Check(bco))
105 return 1;
106 rc = PyInt_AsLong(bco);
107 if (PyErr_Occurred()) {
108 /* not an integer, or too large, or something */
109 PyErr_Clear();
110 rc = 1;
112 return rc != 0; /* convert to values 0, 1 */
115 static PyObject *
116 imageop_crop(PyObject *self, PyObject *args)
118 char *cp, *ncp;
119 short *nsp;
120 Py_Int32 *nlp;
121 int len, size, x, y, newx1, newx2, newy1, newy2, nlen;
122 int ix, iy, xstep, ystep;
123 PyObject *rv;
125 if ( !PyArg_ParseTuple(args, "s#iiiiiii", &cp, &len, &size, &x, &y,
126 &newx1, &newy1, &newx2, &newy2) )
127 return 0;
129 if ( size != 1 && size != 2 && size != 4 ) {
130 PyErr_SetString(ImageopError, "Size should be 1, 2 or 4");
131 return 0;
133 if ( !check_multiply_size(len, x, "x", y, "y", size) )
134 return 0;
136 xstep = (newx1 < newx2)? 1 : -1;
137 ystep = (newy1 < newy2)? 1 : -1;
139 nlen = (abs(newx2-newx1)+1)*(abs(newy2-newy1)+1)*size;
140 if ( !check_multiply_size(nlen, abs(newx2-newx1)+1, "abs(newx2-newx1)+1", abs(newy2-newy1)+1, "abs(newy2-newy1)+1", size) )
141 return 0;
142 rv = PyString_FromStringAndSize(NULL, nlen);
143 if ( rv == 0 )
144 return 0;
145 ncp = (char *)PyString_AsString(rv);
146 nsp = (short *)ncp;
147 nlp = (Py_Int32 *)ncp;
148 newy2 += ystep;
149 newx2 += xstep;
150 for( iy = newy1; iy != newy2; iy+=ystep ) {
151 for ( ix = newx1; ix != newx2; ix+=xstep ) {
152 if ( iy < 0 || iy >= y || ix < 0 || ix >= x ) {
153 if ( size == 1 )
154 *ncp++ = 0;
155 else
156 *nlp++ = 0;
157 } else {
158 if ( size == 1 )
159 *ncp++ = *CHARP(cp, x, ix, iy);
160 else if ( size == 2 )
161 *nsp++ = *SHORTP(cp, x, ix, iy);
162 else
163 *nlp++ = *LONGP(cp, x, ix, iy);
167 return rv;
170 static PyObject *
171 imageop_scale(PyObject *self, PyObject *args)
173 char *cp, *ncp;
174 short *nsp;
175 Py_Int32 *nlp;
176 int len, size, x, y, newx, newy, nlen;
177 int ix, iy;
178 int oix, oiy;
179 PyObject *rv;
181 if ( !PyArg_ParseTuple(args, "s#iiiii",
182 &cp, &len, &size, &x, &y, &newx, &newy) )
183 return 0;
185 if ( size != 1 && size != 2 && size != 4 ) {
186 PyErr_SetString(ImageopError, "Size should be 1, 2 or 4");
187 return 0;
189 if ( !check_multiply_size(len, x, "x", y, "y", size) )
190 return 0;
191 nlen = newx*newy*size;
192 if ( !check_multiply_size(nlen, newx, "newx", newy, "newy", size) )
193 return 0;
195 rv = PyString_FromStringAndSize(NULL, nlen);
196 if ( rv == 0 )
197 return 0;
198 ncp = (char *)PyString_AsString(rv);
199 nsp = (short *)ncp;
200 nlp = (Py_Int32 *)ncp;
201 for( iy = 0; iy < newy; iy++ ) {
202 for ( ix = 0; ix < newx; ix++ ) {
203 oix = ix * x / newx;
204 oiy = iy * y / newy;
205 if ( size == 1 )
206 *ncp++ = *CHARP(cp, x, oix, oiy);
207 else if ( size == 2 )
208 *nsp++ = *SHORTP(cp, x, oix, oiy);
209 else
210 *nlp++ = *LONGP(cp, x, oix, oiy);
213 return rv;
216 /* Note: this routine can use a bit of optimizing */
218 static PyObject *
219 imageop_tovideo(PyObject *self, PyObject *args)
221 int maxx, maxy, x, y, len;
222 int i;
223 unsigned char *cp, *ncp;
224 int width;
225 PyObject *rv;
228 if ( !PyArg_ParseTuple(args, "s#iii", &cp, &len, &width, &maxx, &maxy) )
229 return 0;
231 if ( width != 1 && width != 4 ) {
232 PyErr_SetString(ImageopError, "Size should be 1 or 4");
233 return 0;
235 if ( !check_multiply_size(len, maxx, "max", maxy, "maxy", width) )
236 return 0;
238 rv = PyString_FromStringAndSize(NULL, len);
239 if ( rv == 0 )
240 return 0;
241 ncp = (unsigned char *)PyString_AsString(rv);
243 if ( width == 1 ) {
244 memcpy(ncp, cp, maxx); /* Copy first line */
245 ncp += maxx;
246 for (y=1; y<maxy; y++) { /* Interpolate other lines */
247 for(x=0; x<maxx; x++) {
248 i = y*maxx + x;
249 *ncp++ = ((int)cp[i] + (int)cp[i-maxx]) >> 1;
252 } else {
253 memcpy(ncp, cp, maxx*4); /* Copy first line */
254 ncp += maxx*4;
255 for (y=1; y<maxy; y++) { /* Interpolate other lines */
256 for(x=0; x<maxx; x++) {
257 i = (y*maxx + x)*4 + 1;
258 *ncp++ = 0; /* Skip alfa comp */
259 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
260 i++;
261 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
262 i++;
263 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
267 return rv;
270 static PyObject *
271 imageop_grey2mono(PyObject *self, PyObject *args)
273 int tres, x, y, len;
274 unsigned char *cp, *ncp;
275 unsigned char ovalue;
276 PyObject *rv;
277 int i, bit;
280 if ( !PyArg_ParseTuple(args, "s#iii", &cp, &len, &x, &y, &tres) )
281 return 0;
283 if ( !check_multiply(len, x, y) )
284 return 0;
286 rv = PyString_FromStringAndSize(NULL, (len+7)/8);
287 if ( rv == 0 )
288 return 0;
289 ncp = (unsigned char *)PyString_AsString(rv);
291 bit = 0x80;
292 ovalue = 0;
293 for ( i=0; i < len; i++ ) {
294 if ( (int)cp[i] > tres )
295 ovalue |= bit;
296 bit >>= 1;
297 if ( bit == 0 ) {
298 *ncp++ = ovalue;
299 bit = 0x80;
300 ovalue = 0;
303 if ( bit != 0x80 )
304 *ncp++ = ovalue;
305 return rv;
308 static PyObject *
309 imageop_grey2grey4(PyObject *self, PyObject *args)
311 int x, y, len;
312 unsigned char *cp, *ncp;
313 unsigned char ovalue;
314 PyObject *rv;
315 int i;
316 int pos;
319 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
320 return 0;
322 if ( !check_multiply(len, x, y) )
323 return 0;
325 rv = PyString_FromStringAndSize(NULL, (len+1)/2);
326 if ( rv == 0 )
327 return 0;
328 ncp = (unsigned char *)PyString_AsString(rv);
329 pos = 0;
330 ovalue = 0;
331 for ( i=0; i < len; i++ ) {
332 ovalue |= ((int)cp[i] & 0xf0) >> pos;
333 pos += 4;
334 if ( pos == 8 ) {
335 *ncp++ = ovalue;
336 ovalue = 0;
337 pos = 0;
340 if ( pos != 0 )
341 *ncp++ = ovalue;
342 return rv;
345 static PyObject *
346 imageop_grey2grey2(PyObject *self, PyObject *args)
348 int x, y, len;
349 unsigned char *cp, *ncp;
350 unsigned char ovalue;
351 PyObject *rv;
352 int i;
353 int pos;
356 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
357 return 0;
359 if ( !check_multiply(len, x, y) )
360 return 0;
362 rv = PyString_FromStringAndSize(NULL, (len+3)/4);
363 if ( rv == 0 )
364 return 0;
365 ncp = (unsigned char *)PyString_AsString(rv);
366 pos = 0;
367 ovalue = 0;
368 for ( i=0; i < len; i++ ) {
369 ovalue |= ((int)cp[i] & 0xc0) >> pos;
370 pos += 2;
371 if ( pos == 8 ) {
372 *ncp++ = ovalue;
373 ovalue = 0;
374 pos = 0;
377 if ( pos != 0 )
378 *ncp++ = ovalue;
379 return rv;
382 static PyObject *
383 imageop_dither2mono(PyObject *self, PyObject *args)
385 int sum, x, y, len;
386 unsigned char *cp, *ncp;
387 unsigned char ovalue;
388 PyObject *rv;
389 int i, bit;
392 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
393 return 0;
395 if ( !check_multiply(len, x, y) )
396 return 0;
398 rv = PyString_FromStringAndSize(NULL, (len+7)/8);
399 if ( rv == 0 )
400 return 0;
401 ncp = (unsigned char *)PyString_AsString(rv);
403 bit = 0x80;
404 ovalue = 0;
405 sum = 0;
406 for ( i=0; i < len; i++ ) {
407 sum += cp[i];
408 if ( sum >= 256 ) {
409 sum -= 256;
410 ovalue |= bit;
412 bit >>= 1;
413 if ( bit == 0 ) {
414 *ncp++ = ovalue;
415 bit = 0x80;
416 ovalue = 0;
419 if ( bit != 0x80 )
420 *ncp++ = ovalue;
421 return rv;
424 static PyObject *
425 imageop_dither2grey2(PyObject *self, PyObject *args)
427 int x, y, len;
428 unsigned char *cp, *ncp;
429 unsigned char ovalue;
430 PyObject *rv;
431 int i;
432 int pos;
433 int sum = 0, nvalue;
436 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
437 return 0;
439 if ( !check_multiply(len, x, y) )
440 return 0;
442 rv = PyString_FromStringAndSize(NULL, (len+3)/4);
443 if ( rv == 0 )
444 return 0;
445 ncp = (unsigned char *)PyString_AsString(rv);
446 pos = 1;
447 ovalue = 0;
448 for ( i=0; i < len; i++ ) {
449 sum += cp[i];
450 nvalue = sum & 0x180;
451 sum -= nvalue;
452 ovalue |= nvalue >> pos;
453 pos += 2;
454 if ( pos == 9 ) {
455 *ncp++ = ovalue;
456 ovalue = 0;
457 pos = 1;
460 if ( pos != 0 )
461 *ncp++ = ovalue;
462 return rv;
465 static PyObject *
466 imageop_mono2grey(PyObject *self, PyObject *args)
468 int v0, v1, x, y, len, nlen;
469 unsigned char *cp, *ncp;
470 PyObject *rv;
471 int i, bit;
473 if ( !PyArg_ParseTuple(args, "s#iiii", &cp, &len, &x, &y, &v0, &v1) )
474 return 0;
476 nlen = x*y;
477 if ( !check_multiply(nlen, x, y) )
478 return 0;
479 if ( (nlen+7)/8 != len ) {
480 PyErr_SetString(ImageopError, "String has incorrect length");
481 return 0;
484 rv = PyString_FromStringAndSize(NULL, nlen);
485 if ( rv == 0 )
486 return 0;
487 ncp = (unsigned char *)PyString_AsString(rv);
489 bit = 0x80;
490 for ( i=0; i < nlen; i++ ) {
491 if ( *cp & bit )
492 *ncp++ = v1;
493 else
494 *ncp++ = v0;
495 bit >>= 1;
496 if ( bit == 0 ) {
497 bit = 0x80;
498 cp++;
501 return rv;
504 static PyObject *
505 imageop_grey22grey(PyObject *self, PyObject *args)
507 int x, y, len, nlen;
508 unsigned char *cp, *ncp;
509 PyObject *rv;
510 int i, pos, value = 0, nvalue;
512 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
513 return 0;
515 nlen = x*y;
516 if ( !check_multiply(nlen, x, y) ) {
517 return 0;
519 if ( (nlen+3)/4 != len ) {
520 PyErr_SetString(ImageopError, "String has incorrect length");
521 return 0;
524 rv = PyString_FromStringAndSize(NULL, nlen);
525 if ( rv == 0 )
526 return 0;
527 ncp = (unsigned char *)PyString_AsString(rv);
529 pos = 0;
530 for ( i=0; i < nlen; i++ ) {
531 if ( pos == 0 ) {
532 value = *cp++;
533 pos = 8;
535 pos -= 2;
536 nvalue = (value >> pos) & 0x03;
537 *ncp++ = nvalue | (nvalue << 2) |
538 (nvalue << 4) | (nvalue << 6);
540 return rv;
543 static PyObject *
544 imageop_grey42grey(PyObject *self, PyObject *args)
546 int x, y, len, nlen;
547 unsigned char *cp, *ncp;
548 PyObject *rv;
549 int i, pos, value = 0, nvalue;
551 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
552 return 0;
554 nlen = x*y;
555 if ( !check_multiply(nlen, x, y) )
556 return 0;
557 if ( (nlen+1)/2 != len ) {
558 PyErr_SetString(ImageopError, "String has incorrect length");
559 return 0;
562 rv = PyString_FromStringAndSize(NULL, nlen);
563 if ( rv == 0 )
564 return 0;
565 ncp = (unsigned char *)PyString_AsString(rv);
567 pos = 0;
568 for ( i=0; i < nlen; i++ ) {
569 if ( pos == 0 ) {
570 value = *cp++;
571 pos = 8;
573 pos -= 4;
574 nvalue = (value >> pos) & 0x0f;
575 *ncp++ = nvalue | (nvalue << 4);
577 return rv;
580 static PyObject *
581 imageop_rgb2rgb8(PyObject *self, PyObject *args)
583 int x, y, len, nlen;
584 unsigned char *cp;
585 unsigned char *ncp;
586 PyObject *rv;
587 int i, r, g, b;
588 int backward_compatible = imageop_backward_compatible();
590 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
591 return 0;
593 if ( !check_multiply_size(len, x, "x", y, "y", 4) )
594 return 0;
595 nlen = x*y;
596 if ( !check_multiply(nlen, x, y) )
597 return 0;
599 rv = PyString_FromStringAndSize(NULL, nlen);
600 if ( rv == 0 )
601 return 0;
602 ncp = (unsigned char *)PyString_AsString(rv);
604 for ( i=0; i < nlen; i++ ) {
605 /* Bits in source: aaaaaaaa BBbbbbbb GGGggggg RRRrrrrr */
606 if (backward_compatible) {
607 Py_UInt32 value = * (Py_UInt32 *) cp;
608 cp += 4;
609 r = (int) ((value & 0xff) / 255. * 7. + .5);
610 g = (int) (((value >> 8) & 0xff) / 255. * 7. + .5);
611 b = (int) (((value >> 16) & 0xff) / 255. * 3. + .5);
612 } else {
613 cp++; /* skip alpha channel */
614 b = (int) (*cp++ / 255. * 3. + .5);
615 g = (int) (*cp++ / 255. * 7. + .5);
616 r = (int) (*cp++ / 255. * 7. + .5);
618 *ncp++ = (unsigned char)((r<<5) | (b<<3) | g);
620 return rv;
623 static PyObject *
624 imageop_rgb82rgb(PyObject *self, PyObject *args)
626 int x, y, len, nlen;
627 unsigned char *cp;
628 unsigned char *ncp;
629 PyObject *rv;
630 int i, r, g, b;
631 unsigned char value;
632 int backward_compatible = imageop_backward_compatible();
634 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
635 return 0;
637 if ( !check_multiply(len, x, y) )
638 return 0;
639 nlen = x*y*4;
640 if ( !check_multiply_size(nlen, x, "x", y, "y", 4) )
641 return 0;
643 rv = PyString_FromStringAndSize(NULL, nlen);
644 if ( rv == 0 )
645 return 0;
646 ncp = (unsigned char *)PyString_AsString(rv);
648 for ( i=0; i < len; i++ ) {
649 /* Bits in source: RRRBBGGG
650 ** Red and Green are multiplied by 36.5, Blue by 85
652 value = *cp++;
653 r = (value >> 5) & 7;
654 g = (value ) & 7;
655 b = (value >> 3) & 3;
656 r = (r<<5) | (r<<3) | (r>>1);
657 g = (g<<5) | (g<<3) | (g>>1);
658 b = (b<<6) | (b<<4) | (b<<2) | b;
659 if (backward_compatible) {
660 Py_UInt32 nvalue = r | (g<<8) | (b<<16);
661 * (Py_UInt32 *) ncp = nvalue;
662 ncp += 4;
663 } else {
664 *ncp++ = 0;
665 *ncp++ = b;
666 *ncp++ = g;
667 *ncp++ = r;
670 return rv;
673 static PyObject *
674 imageop_rgb2grey(PyObject *self, PyObject *args)
676 int x, y, len, nlen;
677 unsigned char *cp;
678 unsigned char *ncp;
679 PyObject *rv;
680 int i, r, g, b;
681 int nvalue;
682 int backward_compatible = imageop_backward_compatible();
684 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
685 return 0;
687 if ( !check_multiply_size(len, x, "x", y, "y", 4) )
688 return 0;
689 nlen = x*y;
690 if ( !check_multiply(nlen, x, y) )
691 return 0;
693 rv = PyString_FromStringAndSize(NULL, nlen);
694 if ( rv == 0 )
695 return 0;
696 ncp = (unsigned char *)PyString_AsString(rv);
698 for ( i=0; i < nlen; i++ ) {
699 if (backward_compatible) {
700 Py_UInt32 value = * (Py_UInt32 *) cp;
701 cp += 4;
702 r = (int) ((value & 0xff) / 255. * 7. + .5);
703 g = (int) (((value >> 8) & 0xff) / 255. * 7. + .5);
704 b = (int) (((value >> 16) & 0xff) / 255. * 3. + .5);
705 } else {
706 cp++; /* skip alpha channel */
707 b = *cp++;
708 g = *cp++;
709 r = *cp++;
711 nvalue = (int)(0.30*r + 0.59*g + 0.11*b);
712 if ( nvalue > 255 ) nvalue = 255;
713 *ncp++ = (unsigned char)nvalue;
715 return rv;
718 static PyObject *
719 imageop_grey2rgb(PyObject *self, PyObject *args)
721 int x, y, len, nlen;
722 unsigned char *cp;
723 unsigned char *ncp;
724 PyObject *rv;
725 int i;
726 unsigned char value;
727 int backward_compatible = imageop_backward_compatible();
729 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
730 return 0;
732 if ( !check_multiply(len, x, y) )
733 return 0;
734 nlen = x*y*4;
735 if ( !check_multiply_size(nlen, x, "x", y, "y", 4) )
736 return 0;
738 rv = PyString_FromStringAndSize(NULL, nlen);
739 if ( rv == 0 )
740 return 0;
741 ncp = (unsigned char *)PyString_AsString(rv);
743 for ( i=0; i < len; i++ ) {
744 value = *cp++;
745 if (backward_compatible) {
746 * (Py_UInt32 *) ncp = (Py_UInt32) value | ((Py_UInt32) value << 8 ) | ((Py_UInt32) value << 16);
747 ncp += 4;
748 } else {
749 *ncp++ = 0;
750 *ncp++ = value;
751 *ncp++ = value;
752 *ncp++ = value;
755 return rv;
758 static PyMethodDef imageop_methods[] = {
759 { "crop", imageop_crop, METH_VARARGS },
760 { "scale", imageop_scale, METH_VARARGS },
761 { "grey2mono", imageop_grey2mono, METH_VARARGS },
762 { "grey2grey2", imageop_grey2grey2, METH_VARARGS },
763 { "grey2grey4", imageop_grey2grey4, METH_VARARGS },
764 { "dither2mono", imageop_dither2mono, METH_VARARGS },
765 { "dither2grey2", imageop_dither2grey2, METH_VARARGS },
766 { "mono2grey", imageop_mono2grey, METH_VARARGS },
767 { "grey22grey", imageop_grey22grey, METH_VARARGS },
768 { "grey42grey", imageop_grey42grey, METH_VARARGS },
769 { "tovideo", imageop_tovideo, METH_VARARGS },
770 { "rgb2rgb8", imageop_rgb2rgb8, METH_VARARGS },
771 { "rgb82rgb", imageop_rgb82rgb, METH_VARARGS },
772 { "rgb2grey", imageop_rgb2grey, METH_VARARGS },
773 { "grey2rgb", imageop_grey2rgb, METH_VARARGS },
774 { 0, 0 }
778 PyMODINIT_FUNC
779 initimageop(void)
781 PyObject *m;
783 if (PyErr_WarnPy3k("the imageop module has been removed in "
784 "Python 3.0", 2) < 0)
785 return;
787 m = Py_InitModule("imageop", imageop_methods);
788 if (m == NULL)
789 return;
790 ImageopDict = PyModule_GetDict(m);
791 ImageopError = PyErr_NewException("imageop.error", NULL, NULL);
792 if (ImageopError != NULL)
793 PyDict_SetItemString(ImageopDict, "error", ImageopError);