2 /* imageopmodule - Various operations on pictures */
12 typedef unsigned int Py_UInt32
;
15 typedef long Py_Int32
;
16 typedef unsigned long Py_UInt32
;
18 #error "No 4-byte integral type"
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
;
29 imageop_crop(PyObject
*self
, PyObject
*args
)
34 int len
, size
, x
, y
, newx1
, newx2
, newy1
, newy2
;
35 int ix
, iy
, xstep
, ystep
;
38 if ( !PyArg_Parse(args
, "(s#iiiiiii)", &cp
, &len
, &size
, &x
, &y
,
39 &newx1
, &newy1
, &newx2
, &newy2
) )
42 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
43 PyErr_SetString(ImageopError
, "Size should be 1, 2 or 4");
46 if ( len
!= size
*x
*y
) {
47 PyErr_SetString(ImageopError
, "String has incorrect length");
50 xstep
= (newx1
< newx2
)? 1 : -1;
51 ystep
= (newy1
< newy2
)? 1 : -1;
53 rv
= PyString_FromStringAndSize(NULL
,
54 (abs(newx2
-newx1
)+1)*(abs(newy2
-newy1
)+1)*size
);
57 ncp
= (char *)PyString_AsString(rv
);
59 nlp
= (Py_Int32
*)ncp
;
62 for( iy
= newy1
; iy
!= newy2
; iy
+=ystep
) {
63 for ( ix
= newx1
; ix
!= newx2
; ix
+=xstep
) {
64 if ( iy
< 0 || iy
>= y
|| ix
< 0 || ix
>= x
) {
71 *ncp
++ = *CHARP(cp
, x
, ix
, iy
);
73 *nsp
++ = *SHORTP(cp
, x
, ix
, iy
);
75 *nlp
++ = *LONGP(cp
, x
, ix
, iy
);
83 imageop_scale(PyObject
*self
, PyObject
*args
)
88 int len
, size
, x
, y
, newx
, newy
;
93 if ( !PyArg_Parse(args
, "(s#iiiii)",
94 &cp
, &len
, &size
, &x
, &y
, &newx
, &newy
) )
97 if ( size
!= 1 && size
!= 2 && size
!= 4 ) {
98 PyErr_SetString(ImageopError
, "Size should be 1, 2 or 4");
101 if ( len
!= size
*x
*y
) {
102 PyErr_SetString(ImageopError
, "String has incorrect length");
106 rv
= PyString_FromStringAndSize(NULL
, newx
*newy
*size
);
109 ncp
= (char *)PyString_AsString(rv
);
111 nlp
= (Py_Int32
*)ncp
;
112 for( iy
= 0; iy
< newy
; iy
++ ) {
113 for ( ix
= 0; ix
< newx
; ix
++ ) {
117 *ncp
++ = *CHARP(cp
, x
, oix
, oiy
);
118 else if ( size
== 2 )
119 *nsp
++ = *SHORTP(cp
, x
, oix
, oiy
);
121 *nlp
++ = *LONGP(cp
, x
, oix
, oiy
);
127 /* Note: this routine can use a bit of optimizing */
130 imageop_tovideo(PyObject
*self
, PyObject
*args
)
132 int maxx
, maxy
, x
, y
, len
;
134 unsigned char *cp
, *ncp
;
139 if ( !PyArg_Parse(args
, "(s#iii)", &cp
, &len
, &width
, &maxx
, &maxy
) )
142 if ( width
!= 1 && width
!= 4 ) {
143 PyErr_SetString(ImageopError
, "Size should be 1 or 4");
146 if ( maxx
*maxy
*width
!= len
) {
147 PyErr_SetString(ImageopError
, "String has incorrect length");
151 rv
= PyString_FromStringAndSize(NULL
, len
);
154 ncp
= (unsigned char *)PyString_AsString(rv
);
157 memcpy(ncp
, cp
, maxx
); /* Copy first line */
159 for (y
=1; y
<maxy
; y
++) { /* Interpolate other lines */
160 for(x
=0; x
<maxx
; x
++) {
162 *ncp
++ = ((int)cp
[i
] + (int)cp
[i
-maxx
]) >> 1;
166 memcpy(ncp
, cp
, maxx
*4); /* Copy first line */
168 for (y
=1; y
<maxy
; y
++) { /* Interpolate other lines */
169 for(x
=0; x
<maxx
; x
++) {
170 i
= (y
*maxx
+ x
)*4 + 1;
171 *ncp
++ = 0; /* Skip alfa comp */
172 *ncp
++ = ((int)cp
[i
] + (int)cp
[i
-4*maxx
]) >> 1;
174 *ncp
++ = ((int)cp
[i
] + (int)cp
[i
-4*maxx
]) >> 1;
176 *ncp
++ = ((int)cp
[i
] + (int)cp
[i
-4*maxx
]) >> 1;
184 imageop_grey2mono(PyObject
*self
, PyObject
*args
)
187 unsigned char *cp
, *ncp
;
188 unsigned char ovalue
;
193 if ( !PyArg_Parse(args
, "(s#iii)", &cp
, &len
, &x
, &y
, &tres
) )
197 PyErr_SetString(ImageopError
, "String has incorrect length");
201 rv
= PyString_FromStringAndSize(NULL
, (len
+7)/8);
204 ncp
= (unsigned char *)PyString_AsString(rv
);
208 for ( i
=0; i
< len
; i
++ ) {
209 if ( (int)cp
[i
] > tres
)
224 imageop_grey2grey4(PyObject
*self
, PyObject
*args
)
227 unsigned char *cp
, *ncp
;
228 unsigned char ovalue
;
234 if ( !PyArg_Parse(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
238 PyErr_SetString(ImageopError
, "String has incorrect length");
242 rv
= PyString_FromStringAndSize(NULL
, (len
+1)/2);
245 ncp
= (unsigned char *)PyString_AsString(rv
);
248 for ( i
=0; i
< len
; i
++ ) {
249 ovalue
|= ((int)cp
[i
] & 0xf0) >> pos
;
263 imageop_grey2grey2(PyObject
*self
, PyObject
*args
)
266 unsigned char *cp
, *ncp
;
267 unsigned char ovalue
;
273 if ( !PyArg_Parse(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
277 PyErr_SetString(ImageopError
, "String has incorrect length");
281 rv
= PyString_FromStringAndSize(NULL
, (len
+3)/4);
284 ncp
= (unsigned char *)PyString_AsString(rv
);
287 for ( i
=0; i
< len
; i
++ ) {
288 ovalue
|= ((int)cp
[i
] & 0xc0) >> pos
;
302 imageop_dither2mono(PyObject
*self
, PyObject
*args
)
305 unsigned char *cp
, *ncp
;
306 unsigned char ovalue
;
311 if ( !PyArg_Parse(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
315 PyErr_SetString(ImageopError
, "String has incorrect length");
319 rv
= PyString_FromStringAndSize(NULL
, (len
+7)/8);
322 ncp
= (unsigned char *)PyString_AsString(rv
);
327 for ( i
=0; i
< len
; i
++ ) {
346 imageop_dither2grey2(PyObject
*self
, PyObject
*args
)
349 unsigned char *cp
, *ncp
;
350 unsigned char ovalue
;
357 if ( !PyArg_Parse(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
361 PyErr_SetString(ImageopError
, "String has incorrect length");
365 rv
= PyString_FromStringAndSize(NULL
, (len
+3)/4);
368 ncp
= (unsigned char *)PyString_AsString(rv
);
371 for ( i
=0; i
< len
; i
++ ) {
373 nvalue
= sum
& 0x180;
375 ovalue
|= nvalue
>> pos
;
389 imageop_mono2grey(PyObject
*self
, PyObject
*args
)
391 int v0
, v1
, x
, y
, len
, nlen
;
392 unsigned char *cp
, *ncp
;
396 if ( !PyArg_Parse(args
, "(s#iiii)", &cp
, &len
, &x
, &y
, &v0
, &v1
) )
400 if ( (nlen
+7)/8 != len
) {
401 PyErr_SetString(ImageopError
, "String has incorrect length");
405 rv
= PyString_FromStringAndSize(NULL
, nlen
);
408 ncp
= (unsigned char *)PyString_AsString(rv
);
411 for ( i
=0; i
< nlen
; i
++ ) {
426 imageop_grey22grey(PyObject
*self
, PyObject
*args
)
429 unsigned char *cp
, *ncp
;
431 int i
, pos
, value
= 0, nvalue
;
433 if ( !PyArg_Parse(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
437 if ( (nlen
+3)/4 != len
) {
438 PyErr_SetString(ImageopError
, "String has incorrect length");
442 rv
= PyString_FromStringAndSize(NULL
, nlen
);
445 ncp
= (unsigned char *)PyString_AsString(rv
);
448 for ( i
=0; i
< nlen
; i
++ ) {
454 nvalue
= (value
>> pos
) & 0x03;
455 *ncp
++ = nvalue
| (nvalue
<< 2) |
456 (nvalue
<< 4) | (nvalue
<< 6);
462 imageop_grey42grey(PyObject
*self
, PyObject
*args
)
465 unsigned char *cp
, *ncp
;
467 int i
, pos
, value
= 0, nvalue
;
469 if ( !PyArg_Parse(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
473 if ( (nlen
+1)/2 != len
) {
474 PyErr_SetString(ImageopError
, "String has incorrect length");
478 rv
= PyString_FromStringAndSize(NULL
, nlen
);
481 ncp
= (unsigned char *)PyString_AsString(rv
);
484 for ( i
=0; i
< nlen
; i
++ ) {
490 nvalue
= (value
>> pos
) & 0x0f;
491 *ncp
++ = nvalue
| (nvalue
<< 4);
497 imageop_rgb2rgb8(PyObject
*self
, PyObject
*args
)
504 Py_UInt32 value
, nvalue
;
506 if ( !PyArg_Parse(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
510 if ( nlen
*4 != len
) {
511 PyErr_SetString(ImageopError
, "String has incorrect length");
515 rv
= PyString_FromStringAndSize(NULL
, nlen
);
518 ncp
= (unsigned char *)PyString_AsString(rv
);
520 for ( i
=0; i
< nlen
; i
++ ) {
521 /* Bits in source: aaaaaaaa BBbbbbbb GGGggggg RRRrrrrr */
524 r
= (value
>> 5) & 7;
525 g
= (value
>> 13) & 7;
526 b
= (value
>> 22) & 3;
528 r
= (int) ((value
& 0xff) / 255. * 7. + .5);
529 g
= (int) (((value
>> 8) & 0xff) / 255. * 7. + .5);
530 b
= (int) (((value
>> 16) & 0xff) / 255. * 3. + .5);
532 nvalue
= (r
<<5) | (b
<<3) | g
;
533 *ncp
++ = (unsigned char)nvalue
;
539 imageop_rgb82rgb(PyObject
*self
, PyObject
*args
)
546 Py_UInt32 value
, nvalue
;
548 if ( !PyArg_Parse(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
553 PyErr_SetString(ImageopError
, "String has incorrect length");
557 rv
= PyString_FromStringAndSize(NULL
, nlen
*4);
560 ncp
= (Py_UInt32
*)PyString_AsString(rv
);
562 for ( i
=0; i
< nlen
; i
++ ) {
563 /* Bits in source: RRRBBGGG
564 ** Red and Green are multiplied by 36.5, Blue by 85
567 r
= (value
>> 5) & 7;
569 b
= (value
>> 3) & 3;
570 r
= (r
<<5) | (r
<<3) | (r
>>1);
571 g
= (g
<<5) | (g
<<3) | (g
>>1);
572 b
= (b
<<6) | (b
<<4) | (b
<<2) | b
;
573 nvalue
= r
| (g
<<8) | (b
<<16);
580 imageop_rgb2grey(PyObject
*self
, PyObject
*args
)
587 Py_UInt32 value
, nvalue
;
589 if ( !PyArg_Parse(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
593 if ( nlen
*4 != len
) {
594 PyErr_SetString(ImageopError
, "String has incorrect length");
598 rv
= PyString_FromStringAndSize(NULL
, nlen
);
601 ncp
= (unsigned char *)PyString_AsString(rv
);
603 for ( i
=0; i
< nlen
; i
++ ) {
606 g
= (value
>> 8) & 0xff;
607 b
= (value
>> 16) & 0xff;
608 nvalue
= (int)(0.30*r
+ 0.59*g
+ 0.11*b
);
609 if ( nvalue
> 255 ) nvalue
= 255;
610 *ncp
++ = (unsigned char)nvalue
;
616 imageop_grey2rgb(PyObject
*self
, PyObject
*args
)
625 if ( !PyArg_Parse(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
630 PyErr_SetString(ImageopError
, "String has incorrect length");
634 rv
= PyString_FromStringAndSize(NULL
, nlen
*4);
637 ncp
= (Py_UInt32
*)PyString_AsString(rv
);
639 for ( i
=0; i
< nlen
; i
++ ) {
641 *ncp
++ = value
| (value
<< 8 ) | (value
<< 16);
648 imageop_mul(object *self, object *args)
655 if ( !getargs(args, "(s#iii)", &cp, &len, &size, &x, &y) )
658 if ( size != 1 && size != 4 ) {
659 err_setstr(ImageopError, "Size should be 1 or 4");
662 if ( len != size*x*y ) {
663 err_setstr(ImageopError, "String has incorrect length");
667 rv = newsizedstringobject(NULL, XXXX);
670 ncp = (char *)getstringvalue(rv);
673 for ( i=0; i < len; i += size ) {
679 static PyMethodDef imageop_methods
[] = {
680 { "crop", imageop_crop
},
681 { "scale", imageop_scale
},
682 { "grey2mono", imageop_grey2mono
},
683 { "grey2grey2", imageop_grey2grey2
},
684 { "grey2grey4", imageop_grey2grey4
},
685 { "dither2mono", imageop_dither2mono
},
686 { "dither2grey2", imageop_dither2grey2
},
687 { "mono2grey", imageop_mono2grey
},
688 { "grey22grey", imageop_grey22grey
},
689 { "grey42grey", imageop_grey42grey
},
690 { "tovideo", imageop_tovideo
},
691 { "rgb2rgb8", imageop_rgb2rgb8
},
692 { "rgb82rgb", imageop_rgb82rgb
},
693 { "rgb2grey", imageop_rgb2grey
},
694 { "grey2rgb", imageop_grey2rgb
},
703 m
= Py_InitModule("imageop", imageop_methods
);
704 d
= PyModule_GetDict(m
);
705 ImageopError
= PyErr_NewException("imageop.error", NULL
, NULL
);
706 if (ImageopError
!= NULL
)
707 PyDict_SetItemString(d
, "error", ImageopError
);