1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
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 */
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
;
40 imageop_crop(self
, args
)
46 int len
, size
, x
, y
, newx1
, newx2
, newy1
, newy2
;
47 int ix
, iy
, xstep
, ystep
;
50 if ( !getargs(args
, "(s#iiiiiii)", &cp
, &len
, &size
, &x
, &y
,
51 &newx1
, &newy1
, &newx2
, &newy2
) )
54 if ( size
!= 1 && size
!= 4 ) {
55 err_setstr(ImageopError
, "Size should be 1 or 4");
58 if ( len
!= size
*x
*y
) {
59 err_setstr(ImageopError
, "String has incorrect length");
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
);
69 ncp
= (char *)getstringvalue(rv
);
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;
79 if ( size
== 1 ) *ncp
++ = *CHARP(cp
, x
, ix
, iy
);
80 else *nlp
++ = *LONGP(cp
, x
, ix
, iy
);
88 imageop_scale(self
, args
)
94 int len
, size
, x
, y
, newx
, newy
;
99 if ( !getargs(args
, "(s#iiiii)", &cp
, &len
, &size
, &x
, &y
, &newx
, &newy
) )
102 if ( size
!= 1 && size
!= 4 ) {
103 err_setstr(ImageopError
, "Size should be 1 or 4");
106 if ( len
!= size
*x
*y
) {
107 err_setstr(ImageopError
, "String has incorrect length");
111 rv
= newsizedstringobject(NULL
, newx
*newy
*size
);
114 ncp
= (char *)getstringvalue(rv
);
116 for( iy
= 0; iy
< newy
; iy
++ ) {
117 for ( ix
= 0; ix
< newx
; ix
++ ) {
120 if ( size
== 1 ) *ncp
++ = *CHARP(cp
, x
, oix
, oiy
);
121 else *nlp
++ = *LONGP(cp
, x
, oix
, oiy
);
127 /* Note: this routine can use a bit of optimizing */
130 imageop_tovideo(self
, args
)
134 int maxx
, maxy
, x
, y
, len
;
136 unsigned char *cp
, *ncp
;
141 if ( !getargs(args
, "(s#iii)", &cp
, &len
, &width
, &maxx
, &maxy
) )
144 if ( width
!= 1 && width
!= 4 ) {
145 err_setstr(ImageopError
, "Size should be 1 or 4");
148 if ( maxx
*maxy
*width
!= len
) {
149 err_setstr(ImageopError
, "String has incorrect length");
153 rv
= newsizedstringobject(NULL
, len
);
156 ncp
= (unsigned char *)getstringvalue(rv
);
159 memcpy(ncp
, cp
, maxx
); /* Copy first line */
161 for (y
=1; y
<maxy
; y
++) { /* Interpolate other lines */
162 for(x
=0; x
<maxx
; x
++) {
164 *ncp
++ = ((int)cp
[i
] + (int)cp
[i
-maxx
]) >> 1;
168 memcpy(ncp
, cp
, maxx
*4); /* Copy first line */
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;
176 *ncp
++ = ((int)cp
[i
] + (int)cp
[i
-4*maxx
]) >> 1;
178 *ncp
++ = ((int)cp
[i
] + (int)cp
[i
-4*maxx
]) >> 1;
186 imageop_grey2mono(self
, args
)
191 unsigned char *cp
, *ncp
;
192 unsigned char ovalue
;
197 if ( !getargs(args
, "(s#iii)", &cp
, &len
, &x
, &y
, &tres
) )
201 err_setstr(ImageopError
, "String has incorrect length");
205 rv
= newsizedstringobject(NULL
, (len
+7)/8);
208 ncp
= (unsigned char *)getstringvalue(rv
);
212 for ( i
=0; i
< len
; i
++ ) {
213 if ( (int)cp
[i
] > tres
)
228 imageop_grey2grey4(self
, args
)
233 unsigned char *cp
, *ncp
;
234 unsigned char ovalue
;
240 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
244 err_setstr(ImageopError
, "String has incorrect length");
248 rv
= newsizedstringobject(NULL
, (len
+1)/2);
251 ncp
= (unsigned char *)getstringvalue(rv
);
254 for ( i
=0; i
< len
; i
++ ) {
255 ovalue
|= ((int)cp
[i
] & 0xf0) >> pos
;
269 imageop_grey2grey2(self
, args
)
274 unsigned char *cp
, *ncp
;
275 unsigned char ovalue
;
281 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
285 err_setstr(ImageopError
, "String has incorrect length");
289 rv
= newsizedstringobject(NULL
, (len
+3)/4);
292 ncp
= (unsigned char *)getstringvalue(rv
);
295 for ( i
=0; i
< len
; i
++ ) {
296 ovalue
|= ((int)cp
[i
] & 0xc0) >> pos
;
310 imageop_dither2mono(self
, args
)
315 unsigned char *cp
, *ncp
;
316 unsigned char ovalue
;
321 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
325 err_setstr(ImageopError
, "String has incorrect length");
329 rv
= newsizedstringobject(NULL
, (len
+7)/8);
332 ncp
= (unsigned char *)getstringvalue(rv
);
337 for ( i
=0; i
< len
; i
++ ) {
356 imageop_dither2grey2(self
, args
)
361 unsigned char *cp
, *ncp
;
362 unsigned char ovalue
;
369 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
373 err_setstr(ImageopError
, "String has incorrect length");
377 rv
= newsizedstringobject(NULL
, (len
+3)/4);
380 ncp
= (unsigned char *)getstringvalue(rv
);
383 for ( i
=0; i
< len
; i
++ ) {
385 nvalue
= sum
& 0x180;
387 ovalue
|= nvalue
>> pos
;
401 imageop_mono2grey(self
, args
)
405 int v0
, v1
, x
, y
, len
, nlen
;
406 unsigned char *cp
, *ncp
;
410 if ( !getargs(args
, "(s#iiii)", &cp
, &len
, &x
, &y
, &v0
, &v1
) )
414 if ( (nlen
+7)/8 != len
) {
415 err_setstr(ImageopError
, "String has incorrect length");
419 rv
= newsizedstringobject(NULL
, nlen
);
422 ncp
= (unsigned char *)getstringvalue(rv
);
425 for ( i
=0; i
< nlen
; i
++ ) {
440 imageop_grey22grey(self
, args
)
445 unsigned char *cp
, *ncp
;
447 int i
, pos
, value
, nvalue
;
449 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
453 if ( (nlen
+3)/4 != len
) {
454 err_setstr(ImageopError
, "String has incorrect length");
458 rv
= newsizedstringobject(NULL
, nlen
);
461 ncp
= (unsigned char *)getstringvalue(rv
);
464 for ( i
=0; i
< nlen
; i
++ ) {
470 nvalue
= (value
>> pos
) & 0x03;
471 *ncp
++ = nvalue
| (nvalue
<< 2) | (nvalue
<< 4) | (nvalue
<< 6);
477 imageop_grey42grey(self
, args
)
482 unsigned char *cp
, *ncp
;
484 int i
, pos
, value
, nvalue
;
486 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
490 if ( (nlen
+1)/2 != len
) {
491 err_setstr(ImageopError
, "String has incorrect length");
495 rv
= newsizedstringobject(NULL
, nlen
);
498 ncp
= (unsigned char *)getstringvalue(rv
);
501 for ( i
=0; i
< nlen
; i
++ ) {
507 nvalue
= (value
>> pos
) & 0x0f;
508 *ncp
++ = nvalue
| (nvalue
<< 4);
514 imageop_rgb2rgb8(self
, args
)
523 unsigned long value
, nvalue
;
525 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
529 if ( nlen
*4 != len
) {
530 err_setstr(ImageopError
, "String has incorrect length");
534 rv
= newsizedstringobject(NULL
, nlen
);
537 ncp
= (unsigned char *)getstringvalue(rv
);
539 for ( i
=0; i
< nlen
; i
++ ) {
540 /* Bits in source: aaaaaaaa BBbbbbbb GGGggggg RRRrrrrr */
543 r
= (value
>> 5) & 7;
544 g
= (value
>> 13) & 7;
545 b
= (value
>> 22) & 3;
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);
551 nvalue
= (r
<<5) | (b
<<3) | g
;
558 imageop_rgb82rgb(self
, args
)
567 unsigned long value
, nvalue
;
569 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
574 err_setstr(ImageopError
, "String has incorrect length");
578 rv
= newsizedstringobject(NULL
, nlen
*4);
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
588 r
= (value
>> 5) & 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);
601 imageop_rgb2grey(self
, args
)
610 unsigned long value
, nvalue
;
612 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
616 if ( nlen
*4 != len
) {
617 err_setstr(ImageopError
, "String has incorrect length");
621 rv
= newsizedstringobject(NULL
, nlen
);
624 ncp
= (unsigned char *)getstringvalue(rv
);
626 for ( i
=0; i
< nlen
; i
++ ) {
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;
639 imageop_grey2rgb(self
, args
)
650 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
655 err_setstr(ImageopError
, "String has incorrect length");
659 rv
= newsizedstringobject(NULL
, nlen
*4);
662 ncp
= (unsigned long *)getstringvalue(rv
);
664 for ( i
=0; i
< nlen
; i
++ ) {
666 *ncp
++ = value
| (value
<< 8 ) | (value
<< 16);
673 imageop_mul(self, args)
682 if ( !getargs(args, "(s#iii)", &cp, &len, &size, &x, &y) )
685 if ( size != 1 && size != 4 ) {
686 err_setstr(ImageopError, "Size should be 1 or 4");
689 if ( len != size*x*y ) {
690 err_setstr(ImageopError, "String has incorrect length");
694 rv = newsizedstringobject(NULL, XXXX);
697 ncp = (char *)getstringvalue(rv);
700 for ( i=0; i < len; i += size ) {
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
},
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");