1 /***********************************************************
2 Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3 Amsterdam, The Netherlands.
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
, cdata
;
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
;
407 unsigned char ovalue
;
411 if ( !getargs(args
, "(s#iiii)", &cp
, &len
, &x
, &y
, &v0
, &v1
) )
415 if ( (nlen
+7)/8 != len
) {
416 err_setstr(ImageopError
, "String has incorrect length");
420 rv
= newsizedstringobject(NULL
, nlen
);
423 ncp
= (unsigned char *)getstringvalue(rv
);
426 for ( i
=0; i
< nlen
; i
++ ) {
441 imageop_grey22grey(self
, args
)
446 unsigned char *cp
, *ncp
;
447 unsigned char ovalue
;
449 int i
, pos
, value
, nvalue
;
451 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
455 if ( (nlen
+3)/4 != len
) {
456 err_setstr(ImageopError
, "String has incorrect length");
460 rv
= newsizedstringobject(NULL
, nlen
);
463 ncp
= (unsigned char *)getstringvalue(rv
);
466 for ( i
=0; i
< nlen
; i
++ ) {
472 nvalue
= (value
>> pos
) & 0x03;
473 *ncp
++ = nvalue
| (nvalue
<< 2) | (nvalue
<< 4) | (nvalue
<< 6);
479 imageop_grey42grey(self
, args
)
484 unsigned char *cp
, *ncp
;
485 unsigned char ovalue
;
487 int i
, pos
, value
, nvalue
;
489 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
493 if ( (nlen
+1)/2 != len
) {
494 err_setstr(ImageopError
, "String has incorrect length");
498 rv
= newsizedstringobject(NULL
, nlen
);
501 ncp
= (unsigned char *)getstringvalue(rv
);
504 for ( i
=0; i
< nlen
; i
++ ) {
510 nvalue
= (value
>> pos
) & 0x0f;
511 *ncp
++ = nvalue
| (nvalue
<< 4);
517 imageop_rgb2rgb8(self
, args
)
526 unsigned long value
, nvalue
;
528 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
532 if ( nlen
*4 != len
) {
533 err_setstr(ImageopError
, "String has incorrect length");
537 rv
= newsizedstringobject(NULL
, nlen
);
540 ncp
= (unsigned char *)getstringvalue(rv
);
542 for ( i
=0; i
< nlen
; i
++ ) {
543 /* Bits in source: aaaaaaaa BBbbbbbb GGGggggg RRRrrrrr */
546 r
= (value
>> 5) & 7;
547 g
= (value
>> 13) & 7;
548 b
= (value
>> 22) & 3;
550 r
= (int) ((value
& 0xff) / 255. * 7. + .5);
551 g
= (int) (((value
>> 8) & 0xff) / 255. * 7. + .5);
552 b
= (int) (((value
>> 16) & 0xff) / 255. * 3. + .5);
554 nvalue
= (r
<<5) | (b
<<3) | g
;
561 imageop_rgb82rgb(self
, args
)
570 unsigned long value
, nvalue
;
572 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
577 err_setstr(ImageopError
, "String has incorrect length");
581 rv
= newsizedstringobject(NULL
, nlen
*4);
584 ncp
= (unsigned long *)getstringvalue(rv
);
586 for ( i
=0; i
< nlen
; i
++ ) {
587 /* Bits in source: RRRBBGGG
588 ** Red and Green are multiplied by 36.5, Blue by 85
591 r
= (value
>> 5) & 7;
593 b
= (value
>> 3) & 3;
594 r
= (r
<<5) | (r
<<3) | (r
>>1);
595 g
= (g
<<5) | (g
<<3) | (g
>>1);
596 b
= (b
<<6) | (b
<<4) | (b
<<2) | b
;
597 nvalue
= r
| (g
<<8) | (b
<<16);
604 imageop_rgb2grey(self
, args
)
613 unsigned long value
, nvalue
;
615 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
619 if ( nlen
*4 != len
) {
620 err_setstr(ImageopError
, "String has incorrect length");
624 rv
= newsizedstringobject(NULL
, nlen
);
627 ncp
= (unsigned char *)getstringvalue(rv
);
629 for ( i
=0; i
< nlen
; i
++ ) {
632 g
= (value
>> 8) & 0xff;
633 b
= (value
>> 16) & 0xff;
634 nvalue
= (int)(0.30*r
+ 0.59*g
+ 0.11*b
);
635 if ( nvalue
> 255 ) nvalue
= 255;
642 imageop_grey2rgb(self
, args
)
653 if ( !getargs(args
, "(s#ii)", &cp
, &len
, &x
, &y
) )
658 err_setstr(ImageopError
, "String has incorrect length");
662 rv
= newsizedstringobject(NULL
, nlen
*4);
665 ncp
= (unsigned long *)getstringvalue(rv
);
667 for ( i
=0; i
< nlen
; i
++ ) {
669 *ncp
++ = value
| (value
<< 8 ) | (value
<< 16);
676 imageop_mul(self, args)
685 if ( !getargs(args, "(s#iii)", &cp, &len, &size, &x, &y) )
688 if ( size != 1 && size != 4 ) {
689 err_setstr(ImageopError, "Size should be 1 or 4");
692 if ( len != size*x*y ) {
693 err_setstr(ImageopError, "String has incorrect length");
697 rv = newsizedstringobject(NULL, XXXX);
700 ncp = (char *)getstringvalue(rv);
703 for ( i=0; i < len; i += size ) {
709 static struct methodlist imageop_methods
[] = {
710 { "crop", imageop_crop
},
711 { "scale", imageop_scale
},
712 { "grey2mono", imageop_grey2mono
},
713 { "grey2grey2", imageop_grey2grey2
},
714 { "grey2grey4", imageop_grey2grey4
},
715 { "dither2mono", imageop_dither2mono
},
716 { "dither2grey2", imageop_dither2grey2
},
717 { "mono2grey", imageop_mono2grey
},
718 { "grey22grey", imageop_grey22grey
},
719 { "grey42grey", imageop_grey42grey
},
720 { "tovideo", imageop_tovideo
},
721 { "rgb2rgb8", imageop_rgb2rgb8
},
722 { "rgb82rgb", imageop_rgb82rgb
},
723 { "rgb2grey", imageop_rgb2grey
},
724 { "grey2rgb", imageop_grey2rgb
},
733 m
= initmodule("imageop", imageop_methods
);
734 d
= getmoduledict(m
);
735 ImageopError
= newstringobject("imageop.error");
736 if ( ImageopError
== NULL
|| dictinsert(d
,"error",ImageopError
) )
737 fatal("can't define imageop.error");