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