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