Don't reference removed files in Makefile
[python/dscho.git] / Modules / imageop.c
blob431bf50531159a697e59f090a7fb16332a610cd5
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* imageopmodule - Various operations on pictures */
27 #ifdef sun
28 #define signed
29 #endif
31 #include "allobjects.h"
32 #include "modsupport.h"
34 #define CHARP(cp, xmax, x, y) ((char *)(cp+y*xmax+x))
35 #define LONGP(cp, xmax, x, y) ((long *)(cp+4*(y*xmax+x)))
37 static object *ImageopError;
39 static object *
40 imageop_crop(self, args)
41 object *self;
42 object *args;
44 char *cp, *ncp;
45 long *nlp;
46 int len, size, x, y, newx1, newx2, newy1, newy2;
47 int ix, iy, xstep, ystep;
48 object *rv;
50 if ( !getargs(args, "(s#iiiiiii)", &cp, &len, &size, &x, &y,
51 &newx1, &newy1, &newx2, &newy2) )
52 return 0;
54 if ( size != 1 && size != 4 ) {
55 err_setstr(ImageopError, "Size should be 1 or 4");
56 return 0;
58 if ( len != size*x*y ) {
59 err_setstr(ImageopError, "String has incorrect length");
60 return 0;
62 xstep = (newx1 < newx2)? 1 : -1;
63 ystep = (newy1 < newy2)? 1 : -1;
65 rv = newsizedstringobject(NULL,
66 (abs(newx2-newx1)+1)*(abs(newy2-newy1)+1)*size);
67 if ( rv == 0 )
68 return 0;
69 ncp = (char *)getstringvalue(rv);
70 nlp = (long *)ncp;
71 newy2 += ystep;
72 newx2 += xstep;
73 for( iy = newy1; iy != newy2; iy+=ystep ) {
74 for ( ix = newx1; ix != newx2; ix+=xstep ) {
75 if ( iy < 0 || iy >= y || ix < 0 || ix >= x ) {
76 if ( size == 1 ) *ncp++ = 0;
77 else *nlp++ = 0;
78 } else {
79 if ( size == 1 ) *ncp++ = *CHARP(cp, x, ix, iy);
80 else *nlp++ = *LONGP(cp, x, ix, iy);
84 return rv;
87 static object *
88 imageop_scale(self, args)
89 object *self;
90 object *args;
92 char *cp, *ncp;
93 long *nlp;
94 int len, size, x, y, newx, newy;
95 int ix, iy;
96 int oix, oiy;
97 object *rv;
99 if ( !getargs(args, "(s#iiiii)", &cp, &len, &size, &x, &y, &newx, &newy) )
100 return 0;
102 if ( size != 1 && size != 4 ) {
103 err_setstr(ImageopError, "Size should be 1 or 4");
104 return 0;
106 if ( len != size*x*y ) {
107 err_setstr(ImageopError, "String has incorrect length");
108 return 0;
111 rv = newsizedstringobject(NULL, newx*newy*size);
112 if ( rv == 0 )
113 return 0;
114 ncp = (char *)getstringvalue(rv);
115 nlp = (long *)ncp;
116 for( iy = 0; iy < newy; iy++ ) {
117 for ( ix = 0; ix < newx; ix++ ) {
118 oix = ix * x / newx;
119 oiy = iy * y / newy;
120 if ( size == 1 ) *ncp++ = *CHARP(cp, x, oix, oiy);
121 else *nlp++ = *LONGP(cp, x, oix, oiy);
124 return rv;
127 /* Note: this routine can use a bit of optimizing */
129 static object *
130 imageop_tovideo(self, args)
131 object *self;
132 object *args;
134 int maxx, maxy, x, y, len;
135 int i;
136 unsigned char *cp, *ncp;
137 int width;
138 object *rv;
141 if ( !getargs(args, "(s#iii)", &cp, &len, &width, &maxx, &maxy) )
142 return 0;
144 if ( width != 1 && width != 4 ) {
145 err_setstr(ImageopError, "Size should be 1 or 4");
146 return 0;
148 if ( maxx*maxy*width != len ) {
149 err_setstr(ImageopError, "String has incorrect length");
150 return 0;
153 rv = newsizedstringobject(NULL, len);
154 if ( rv == 0 )
155 return 0;
156 ncp = (unsigned char *)getstringvalue(rv);
158 if ( width == 1 ) {
159 memcpy(ncp, cp, maxx); /* Copy first line */
160 ncp += maxx;
161 for (y=1; y<maxy; y++) { /* Interpolate other lines */
162 for(x=0; x<maxx; x++) {
163 i = y*maxx + x;
164 *ncp++ = ((int)cp[i] + (int)cp[i-maxx]) >> 1;
167 } else {
168 memcpy(ncp, cp, maxx*4); /* Copy first line */
169 ncp += maxx*4;
170 for (y=1; y<maxy; y++) { /* Interpolate other lines */
171 for(x=0; x<maxx; x++) {
172 i = (y*maxx + x)*4 + 1;
173 *ncp++ = 0; /* Skip alfa comp */
174 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
175 i++;
176 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
177 i++;
178 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
182 return rv;
185 static object *
186 imageop_grey2mono(self, args)
187 object *self;
188 object *args;
190 int tres, x, y, len;
191 unsigned char *cp, *ncp;
192 unsigned char ovalue;
193 object *rv;
194 int i, bit;
197 if ( !getargs(args, "(s#iii)", &cp, &len, &x, &y, &tres) )
198 return 0;
200 if ( x*y != len ) {
201 err_setstr(ImageopError, "String has incorrect length");
202 return 0;
205 rv = newsizedstringobject(NULL, (len+7)/8);
206 if ( rv == 0 )
207 return 0;
208 ncp = (unsigned char *)getstringvalue(rv);
210 bit = 0x80;
211 ovalue = 0;
212 for ( i=0; i < len; i++ ) {
213 if ( (int)cp[i] > tres )
214 ovalue |= bit;
215 bit >>= 1;
216 if ( bit == 0 ) {
217 *ncp++ = ovalue;
218 bit = 0x80;
219 ovalue = 0;
222 if ( bit != 0x80 )
223 *ncp++ = ovalue;
224 return rv;
227 static object *
228 imageop_grey2grey4(self, args)
229 object *self;
230 object *args;
232 int x, y, len;
233 unsigned char *cp, *ncp;
234 unsigned char ovalue;
235 object *rv;
236 int i;
237 int pos;
240 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
241 return 0;
243 if ( x*y != len ) {
244 err_setstr(ImageopError, "String has incorrect length");
245 return 0;
248 rv = newsizedstringobject(NULL, (len+1)/2);
249 if ( rv == 0 )
250 return 0;
251 ncp = (unsigned char *)getstringvalue(rv);
252 pos = 0;
253 ovalue = 0;
254 for ( i=0; i < len; i++ ) {
255 ovalue |= ((int)cp[i] & 0xf0) >> pos;
256 pos += 4;
257 if ( pos == 8 ) {
258 *ncp++ = ovalue;
259 ovalue = 0;
260 pos = 0;
263 if ( pos != 0 )
264 *ncp++ = ovalue;
265 return rv;
268 static object *
269 imageop_grey2grey2(self, args)
270 object *self;
271 object *args;
273 int x, y, len;
274 unsigned char *cp, *ncp;
275 unsigned char ovalue;
276 object *rv;
277 int i;
278 int pos;
281 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
282 return 0;
284 if ( x*y != len ) {
285 err_setstr(ImageopError, "String has incorrect length");
286 return 0;
289 rv = newsizedstringobject(NULL, (len+3)/4);
290 if ( rv == 0 )
291 return 0;
292 ncp = (unsigned char *)getstringvalue(rv);
293 pos = 0;
294 ovalue = 0;
295 for ( i=0; i < len; i++ ) {
296 ovalue |= ((int)cp[i] & 0xc0) >> pos;
297 pos += 2;
298 if ( pos == 8 ) {
299 *ncp++ = ovalue;
300 ovalue = 0;
301 pos = 0;
304 if ( pos != 0 )
305 *ncp++ = ovalue;
306 return rv;
309 static object *
310 imageop_dither2mono(self, args)
311 object *self;
312 object *args;
314 int sum, x, y, len;
315 unsigned char *cp, *ncp;
316 unsigned char ovalue;
317 object *rv;
318 int i, bit;
321 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
322 return 0;
324 if ( x*y != len ) {
325 err_setstr(ImageopError, "String has incorrect length");
326 return 0;
329 rv = newsizedstringobject(NULL, (len+7)/8);
330 if ( rv == 0 )
331 return 0;
332 ncp = (unsigned char *)getstringvalue(rv);
334 bit = 0x80;
335 ovalue = 0;
336 sum = 0;
337 for ( i=0; i < len; i++ ) {
338 sum += cp[i];
339 if ( sum >= 256 ) {
340 sum -= 256;
341 ovalue |= bit;
343 bit >>= 1;
344 if ( bit == 0 ) {
345 *ncp++ = ovalue;
346 bit = 0x80;
347 ovalue = 0;
350 if ( bit != 0x80 )
351 *ncp++ = ovalue;
352 return rv;
355 static object *
356 imageop_dither2grey2(self, args)
357 object *self;
358 object *args;
360 int x, y, len;
361 unsigned char *cp, *ncp;
362 unsigned char ovalue;
363 object *rv;
364 int i;
365 int pos;
366 int sum = 0, nvalue;
369 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
370 return 0;
372 if ( x*y != len ) {
373 err_setstr(ImageopError, "String has incorrect length");
374 return 0;
377 rv = newsizedstringobject(NULL, (len+3)/4);
378 if ( rv == 0 )
379 return 0;
380 ncp = (unsigned char *)getstringvalue(rv);
381 pos = 1;
382 ovalue = 0;
383 for ( i=0; i < len; i++ ) {
384 sum += cp[i];
385 nvalue = sum & 0x180;
386 sum -= nvalue;
387 ovalue |= nvalue >> pos;
388 pos += 2;
389 if ( pos == 9 ) {
390 *ncp++ = ovalue;
391 ovalue = 0;
392 pos = 1;
395 if ( pos != 0 )
396 *ncp++ = ovalue;
397 return rv;
400 static object *
401 imageop_mono2grey(self, args)
402 object *self;
403 object *args;
405 int v0, v1, x, y, len, nlen;
406 unsigned char *cp, *ncp;
407 object *rv;
408 int i, bit;
410 if ( !getargs(args, "(s#iiii)", &cp, &len, &x, &y, &v0, &v1) )
411 return 0;
413 nlen = x*y;
414 if ( (nlen+7)/8 != len ) {
415 err_setstr(ImageopError, "String has incorrect length");
416 return 0;
419 rv = newsizedstringobject(NULL, nlen);
420 if ( rv == 0 )
421 return 0;
422 ncp = (unsigned char *)getstringvalue(rv);
424 bit = 0x80;
425 for ( i=0; i < nlen; i++ ) {
426 if ( *cp & bit )
427 *ncp++ = v1;
428 else
429 *ncp++ = v0;
430 bit >>= 1;
431 if ( bit == 0 ) {
432 bit = 0x80;
433 cp++;
436 return rv;
439 static object *
440 imageop_grey22grey(self, args)
441 object *self;
442 object *args;
444 int x, y, len, nlen;
445 unsigned char *cp, *ncp;
446 object *rv;
447 int i, pos, value, nvalue;
449 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
450 return 0;
452 nlen = x*y;
453 if ( (nlen+3)/4 != len ) {
454 err_setstr(ImageopError, "String has incorrect length");
455 return 0;
458 rv = newsizedstringobject(NULL, nlen);
459 if ( rv == 0 )
460 return 0;
461 ncp = (unsigned char *)getstringvalue(rv);
463 pos = 0;
464 for ( i=0; i < nlen; i++ ) {
465 if ( pos == 0 ) {
466 value = *cp++;
467 pos = 8;
469 pos -= 2;
470 nvalue = (value >> pos) & 0x03;
471 *ncp++ = nvalue | (nvalue << 2) | (nvalue << 4) | (nvalue << 6);
473 return rv;
476 static object *
477 imageop_grey42grey(self, args)
478 object *self;
479 object *args;
481 int x, y, len, nlen;
482 unsigned char *cp, *ncp;
483 object *rv;
484 int i, pos, value, nvalue;
486 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
487 return 0;
489 nlen = x*y;
490 if ( (nlen+1)/2 != len ) {
491 err_setstr(ImageopError, "String has incorrect length");
492 return 0;
495 rv = newsizedstringobject(NULL, nlen);
496 if ( rv == 0 )
497 return 0;
498 ncp = (unsigned char *)getstringvalue(rv);
500 pos = 0;
501 for ( i=0; i < nlen; i++ ) {
502 if ( pos == 0 ) {
503 value = *cp++;
504 pos = 8;
506 pos -= 4;
507 nvalue = (value >> pos) & 0x0f;
508 *ncp++ = nvalue | (nvalue << 4);
510 return rv;
513 static object *
514 imageop_rgb2rgb8(self, args)
515 object *self;
516 object *args;
518 int x, y, len, nlen;
519 unsigned long *cp;
520 unsigned char *ncp;
521 object *rv;
522 int i, r, g, b;
523 unsigned long value, nvalue;
525 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
526 return 0;
528 nlen = x*y;
529 if ( nlen*4 != len ) {
530 err_setstr(ImageopError, "String has incorrect length");
531 return 0;
534 rv = newsizedstringobject(NULL, nlen);
535 if ( rv == 0 )
536 return 0;
537 ncp = (unsigned char *)getstringvalue(rv);
539 for ( i=0; i < nlen; i++ ) {
540 /* Bits in source: aaaaaaaa BBbbbbbb GGGggggg RRRrrrrr */
541 value = *cp++;
542 #if 0
543 r = (value >> 5) & 7;
544 g = (value >> 13) & 7;
545 b = (value >> 22) & 3;
546 #else
547 r = (int) ((value & 0xff) / 255. * 7. + .5);
548 g = (int) (((value >> 8) & 0xff) / 255. * 7. + .5);
549 b = (int) (((value >> 16) & 0xff) / 255. * 3. + .5);
550 #endif
551 nvalue = (r<<5) | (b<<3) | g;
552 *ncp++ = nvalue;
554 return rv;
557 static object *
558 imageop_rgb82rgb(self, args)
559 object *self;
560 object *args;
562 int x, y, len, nlen;
563 unsigned char *cp;
564 unsigned long *ncp;
565 object *rv;
566 int i, r, g, b;
567 unsigned long value, nvalue;
569 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
570 return 0;
572 nlen = x*y;
573 if ( nlen != len ) {
574 err_setstr(ImageopError, "String has incorrect length");
575 return 0;
578 rv = newsizedstringobject(NULL, nlen*4);
579 if ( rv == 0 )
580 return 0;
581 ncp = (unsigned long *)getstringvalue(rv);
583 for ( i=0; i < nlen; i++ ) {
584 /* Bits in source: RRRBBGGG
585 ** Red and Green are multiplied by 36.5, Blue by 85
587 value = *cp++;
588 r = (value >> 5) & 7;
589 g = (value ) & 7;
590 b = (value >> 3) & 3;
591 r = (r<<5) | (r<<3) | (r>>1);
592 g = (g<<5) | (g<<3) | (g>>1);
593 b = (b<<6) | (b<<4) | (b<<2) | b;
594 nvalue = r | (g<<8) | (b<<16);
595 *ncp++ = nvalue;
597 return rv;
600 static object *
601 imageop_rgb2grey(self, args)
602 object *self;
603 object *args;
605 int x, y, len, nlen;
606 unsigned long *cp;
607 unsigned char *ncp;
608 object *rv;
609 int i, r, g, b;
610 unsigned long value, nvalue;
612 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
613 return 0;
615 nlen = x*y;
616 if ( nlen*4 != len ) {
617 err_setstr(ImageopError, "String has incorrect length");
618 return 0;
621 rv = newsizedstringobject(NULL, nlen);
622 if ( rv == 0 )
623 return 0;
624 ncp = (unsigned char *)getstringvalue(rv);
626 for ( i=0; i < nlen; i++ ) {
627 value = *cp++;
628 r = (value ) & 0xff;
629 g = (value >> 8) & 0xff;
630 b = (value >> 16) & 0xff;
631 nvalue = (int)(0.30*r + 0.59*g + 0.11*b);
632 if ( nvalue > 255 ) nvalue = 255;
633 *ncp++ = nvalue;
635 return rv;
638 static object *
639 imageop_grey2rgb(self, args)
640 object *self;
641 object *args;
643 int x, y, len, nlen;
644 unsigned char *cp;
645 unsigned long *ncp;
646 object *rv;
647 int i;
648 unsigned long value;
650 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
651 return 0;
653 nlen = x*y;
654 if ( nlen != len ) {
655 err_setstr(ImageopError, "String has incorrect length");
656 return 0;
659 rv = newsizedstringobject(NULL, nlen*4);
660 if ( rv == 0 )
661 return 0;
662 ncp = (unsigned long *)getstringvalue(rv);
664 for ( i=0; i < nlen; i++ ) {
665 value = *cp++;
666 *ncp++ = value | (value << 8 ) | (value << 16);
668 return rv;
672 static object *
673 imageop_mul(self, args)
674 object *self;
675 object *args;
677 char *cp, *ncp;
678 int len, size, x, y;
679 object *rv;
680 int i;
682 if ( !getargs(args, "(s#iii)", &cp, &len, &size, &x, &y) )
683 return 0;
685 if ( size != 1 && size != 4 ) {
686 err_setstr(ImageopError, "Size should be 1 or 4");
687 return 0;
689 if ( len != size*x*y ) {
690 err_setstr(ImageopError, "String has incorrect length");
691 return 0;
694 rv = newsizedstringobject(NULL, XXXX);
695 if ( rv == 0 )
696 return 0;
697 ncp = (char *)getstringvalue(rv);
700 for ( i=0; i < len; i += size ) {
702 return rv;
706 static struct methodlist imageop_methods[] = {
707 { "crop", imageop_crop },
708 { "scale", imageop_scale },
709 { "grey2mono", imageop_grey2mono },
710 { "grey2grey2", imageop_grey2grey2 },
711 { "grey2grey4", imageop_grey2grey4 },
712 { "dither2mono", imageop_dither2mono },
713 { "dither2grey2", imageop_dither2grey2 },
714 { "mono2grey", imageop_mono2grey },
715 { "grey22grey", imageop_grey22grey },
716 { "grey42grey", imageop_grey42grey },
717 { "tovideo", imageop_tovideo },
718 { "rgb2rgb8", imageop_rgb2rgb8 },
719 { "rgb82rgb", imageop_rgb82rgb },
720 { "rgb2grey", imageop_rgb2grey },
721 { "grey2rgb", imageop_grey2rgb },
722 { 0, 0 }
726 void
727 initimageop()
729 object *m, *d;
730 m = initmodule("imageop", imageop_methods);
731 d = getmoduledict(m);
732 ImageopError = newstringobject("imageop.error");
733 if ( ImageopError == NULL || dictinsert(d,"error",ImageopError) )
734 fatal("can't define imageop.error");