| Guido van Rossum | 0317a47 | 1992-10-26 13:40:15 +0000 | [diff] [blame] | 1 | /*********************************************************** | 
| Guido van Rossum | 524b588 | 1995-01-04 19:10:35 +0000 | [diff] [blame] | 2 | Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, | 
 | 3 | The Netherlands. | 
| Guido van Rossum | 0317a47 | 1992-10-26 13:40:15 +0000 | [diff] [blame] | 4 |  | 
 | 5 |                         All Rights Reserved | 
 | 6 |  | 
 | 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. | 
 | 14 |  | 
 | 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. | 
 | 22 |  | 
 | 23 | ******************************************************************/ | 
 | 24 |  | 
 | 25 | /* imageopmodule - Various operations on pictures */ | 
 | 26 |  | 
 | 27 | #ifdef sun | 
 | 28 | #define signed | 
 | 29 | #endif | 
 | 30 |  | 
 | 31 | #include "allobjects.h" | 
 | 32 | #include "modsupport.h" | 
 | 33 |  | 
 | 34 | #define CHARP(cp, xmax, x, y) ((char *)(cp+y*xmax+x)) | 
| Jack Jansen | 76c79e9 | 1996-01-22 14:55:15 +0000 | [diff] [blame] | 35 | #define SHORTP(cp, xmax, x, y) ((short *)(cp+2*(y*xmax+x))) | 
| Guido van Rossum | 0317a47 | 1992-10-26 13:40:15 +0000 | [diff] [blame] | 36 | #define LONGP(cp, xmax, x, y) ((long *)(cp+4*(y*xmax+x))) | 
 | 37 |  | 
 | 38 | static object *ImageopError; | 
 | 39 |   | 
 | 40 | static object * | 
 | 41 | imageop_crop(self, args) | 
 | 42 |     object *self; | 
 | 43 |     object *args; | 
 | 44 | { | 
 | 45 |     char *cp, *ncp; | 
| Jack Jansen | 76c79e9 | 1996-01-22 14:55:15 +0000 | [diff] [blame] | 46 |     short *nsp; | 
| Guido van Rossum | 0317a47 | 1992-10-26 13:40:15 +0000 | [diff] [blame] | 47 |     long *nlp; | 
 | 48 |     int len, size, x, y, newx1, newx2, newy1, newy2; | 
 | 49 |     int ix, iy, xstep, ystep; | 
 | 50 |     object *rv; | 
 | 51 |  | 
 | 52 |     if ( !getargs(args, "(s#iiiiiii)", &cp, &len, &size, &x, &y, | 
 | 53 | 		  &newx1, &newy1, &newx2, &newy2) ) | 
 | 54 |       return 0; | 
 | 55 |      | 
| Jack Jansen | 76c79e9 | 1996-01-22 14:55:15 +0000 | [diff] [blame] | 56 |     if ( size != 1 && size != 2 && size != 4 ) { | 
 | 57 | 	err_setstr(ImageopError, "Size should be 1, 2 or 4"); | 
| Guido van Rossum | 0317a47 | 1992-10-26 13:40:15 +0000 | [diff] [blame] | 58 | 	return 0; | 
 | 59 |     } | 
 | 60 |     if ( len != size*x*y ) { | 
 | 61 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 62 | 	return 0; | 
 | 63 |     } | 
 | 64 |     xstep = (newx1 < newx2)? 1 : -1; | 
 | 65 |     ystep = (newy1 < newy2)? 1 : -1; | 
 | 66 |      | 
| Guido van Rossum | 5f59d60 | 1992-12-14 16:59:51 +0000 | [diff] [blame] | 67 |     rv = newsizedstringobject(NULL, | 
 | 68 | 			      (abs(newx2-newx1)+1)*(abs(newy2-newy1)+1)*size); | 
| Guido van Rossum | 0317a47 | 1992-10-26 13:40:15 +0000 | [diff] [blame] | 69 |     if ( rv == 0 ) | 
 | 70 |       return 0; | 
 | 71 |     ncp = (char *)getstringvalue(rv); | 
| Jack Jansen | 76c79e9 | 1996-01-22 14:55:15 +0000 | [diff] [blame] | 72 |     nsp = (short *)ncp; | 
| Guido van Rossum | 0317a47 | 1992-10-26 13:40:15 +0000 | [diff] [blame] | 73 |     nlp = (long *)ncp; | 
 | 74 |     newy2 += ystep; | 
 | 75 |     newx2 += xstep; | 
 | 76 |     for( iy = newy1; iy != newy2; iy+=ystep ) { | 
 | 77 | 	for ( ix = newx1; ix != newx2; ix+=xstep ) { | 
 | 78 | 	    if ( iy < 0 || iy >= y || ix < 0 || ix >= x ) { | 
 | 79 | 	      if ( size == 1 ) *ncp++ = 0; | 
 | 80 | 	      else             *nlp++ = 0; | 
 | 81 | 	    } else { | 
| Jack Jansen | 76c79e9 | 1996-01-22 14:55:15 +0000 | [diff] [blame] | 82 | 		if      ( size == 1 ) *ncp++ = *CHARP(cp, x, ix, iy); | 
 | 83 | 		else if ( size == 2 ) *nsp++ = *SHORTP(cp, x, ix, iy); | 
 | 84 | 		else                  *nlp++ = *LONGP(cp, x, ix, iy); | 
| Guido van Rossum | 0317a47 | 1992-10-26 13:40:15 +0000 | [diff] [blame] | 85 | 	    } | 
 | 86 | 	} | 
 | 87 |     } | 
 | 88 |     return rv; | 
 | 89 | } | 
 | 90 |   | 
 | 91 | static object * | 
 | 92 | imageop_scale(self, args) | 
 | 93 |     object *self; | 
 | 94 |     object *args; | 
 | 95 | { | 
 | 96 |     char *cp, *ncp; | 
| Jack Jansen | 76c79e9 | 1996-01-22 14:55:15 +0000 | [diff] [blame] | 97 |     short *nsp; | 
| Guido van Rossum | 0317a47 | 1992-10-26 13:40:15 +0000 | [diff] [blame] | 98 |     long *nlp; | 
 | 99 |     int len, size, x, y, newx, newy; | 
 | 100 |     int ix, iy; | 
 | 101 |     int oix, oiy; | 
 | 102 |     object *rv; | 
 | 103 |  | 
 | 104 |     if ( !getargs(args, "(s#iiiii)", &cp, &len, &size, &x, &y, &newx, &newy) ) | 
 | 105 |       return 0; | 
 | 106 |      | 
| Jack Jansen | 76c79e9 | 1996-01-22 14:55:15 +0000 | [diff] [blame] | 107 |     if ( size != 1 && size != 2 && size != 4 ) { | 
 | 108 | 	err_setstr(ImageopError, "Size should be 1, 2 or 4"); | 
| Guido van Rossum | 0317a47 | 1992-10-26 13:40:15 +0000 | [diff] [blame] | 109 | 	return 0; | 
 | 110 |     } | 
 | 111 |     if ( len != size*x*y ) { | 
 | 112 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 113 | 	return 0; | 
 | 114 |     } | 
 | 115 |      | 
 | 116 |     rv = newsizedstringobject(NULL, newx*newy*size); | 
 | 117 |     if ( rv == 0 ) | 
 | 118 |       return 0; | 
 | 119 |     ncp = (char *)getstringvalue(rv); | 
| Jack Jansen | 76c79e9 | 1996-01-22 14:55:15 +0000 | [diff] [blame] | 120 |     nsp = (short *)ncp; | 
| Guido van Rossum | 0317a47 | 1992-10-26 13:40:15 +0000 | [diff] [blame] | 121 |     nlp = (long *)ncp; | 
 | 122 |     for( iy = 0; iy < newy; iy++ ) { | 
 | 123 | 	for ( ix = 0; ix < newx; ix++ ) { | 
 | 124 | 	    oix = ix * x / newx; | 
 | 125 | 	    oiy = iy * y / newy; | 
| Jack Jansen | 76c79e9 | 1996-01-22 14:55:15 +0000 | [diff] [blame] | 126 | 	    if      ( size == 1 ) *ncp++ = *CHARP(cp, x, oix, oiy); | 
 | 127 | 	    else if ( size == 2 ) *nsp++ = *SHORTP(cp, x, oix, oiy); | 
 | 128 | 	    else                  *nlp++ = *LONGP(cp, x, oix, oiy); | 
| Guido van Rossum | 0317a47 | 1992-10-26 13:40:15 +0000 | [diff] [blame] | 129 | 	} | 
 | 130 |     } | 
 | 131 |     return rv; | 
 | 132 | } | 
 | 133 |  | 
| Jack Jansen | d26b458 | 1993-01-22 15:34:43 +0000 | [diff] [blame] | 134 | /* Note: this routine can use a bit of optimizing */ | 
 | 135 |  | 
 | 136 | static object * | 
 | 137 | imageop_tovideo(self, args) | 
 | 138 |     object *self; | 
 | 139 |     object *args; | 
 | 140 | { | 
 | 141 |     int maxx, maxy, x, y, len; | 
 | 142 |     int i; | 
| Guido van Rossum | 3bbc62e | 1995-01-02 19:30:30 +0000 | [diff] [blame] | 143 |     unsigned char *cp, *ncp; | 
| Jack Jansen | d26b458 | 1993-01-22 15:34:43 +0000 | [diff] [blame] | 144 |     int width; | 
 | 145 |     object *rv; | 
 | 146 |     | 
 | 147 |      | 
 | 148 |     if ( !getargs(args, "(s#iii)", &cp, &len, &width, &maxx, &maxy) ) | 
 | 149 |       return 0; | 
 | 150 |  | 
 | 151 |     if ( width != 1 && width != 4 ) { | 
 | 152 | 	err_setstr(ImageopError, "Size should be 1 or 4"); | 
 | 153 | 	return 0; | 
 | 154 |     } | 
 | 155 |     if ( maxx*maxy*width != len ) { | 
 | 156 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 157 | 	return 0; | 
 | 158 |     } | 
 | 159 |      | 
 | 160 |     rv = newsizedstringobject(NULL, len); | 
 | 161 |     if ( rv == 0 ) | 
 | 162 |       return 0; | 
 | 163 |     ncp = (unsigned char *)getstringvalue(rv); | 
 | 164 |  | 
 | 165 |     if ( width == 1 ) { | 
| Guido van Rossum | 1fc238a | 1993-07-29 08:25:09 +0000 | [diff] [blame] | 166 | 	memcpy(ncp, cp, maxx);		/* Copy first line */ | 
| Jack Jansen | d26b458 | 1993-01-22 15:34:43 +0000 | [diff] [blame] | 167 | 	ncp += maxx; | 
 | 168 | 	for (y=1; y<maxy; y++) {	/* Interpolate other lines */ | 
 | 169 | 	    for(x=0; x<maxx; x++) { | 
 | 170 | 		i = y*maxx + x; | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 171 | 		*ncp++ = ((int)cp[i] + (int)cp[i-maxx]) >> 1; | 
| Jack Jansen | d26b458 | 1993-01-22 15:34:43 +0000 | [diff] [blame] | 172 | 	    } | 
 | 173 | 	} | 
 | 174 |     } else { | 
| Guido van Rossum | 1fc238a | 1993-07-29 08:25:09 +0000 | [diff] [blame] | 175 | 	memcpy(ncp, cp, maxx*4);		/* Copy first line */ | 
| Jack Jansen | d26b458 | 1993-01-22 15:34:43 +0000 | [diff] [blame] | 176 | 	ncp += maxx*4; | 
 | 177 | 	for (y=1; y<maxy; y++) {	/* Interpolate other lines */ | 
 | 178 | 	    for(x=0; x<maxx; x++) { | 
 | 179 | 		i = (y*maxx + x)*4 + 1; | 
 | 180 | 		*ncp++ = 0;	/* Skip alfa comp */ | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 181 | 		*ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1; | 
| Jack Jansen | d26b458 | 1993-01-22 15:34:43 +0000 | [diff] [blame] | 182 | 		i++; | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 183 | 		*ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1; | 
| Jack Jansen | d26b458 | 1993-01-22 15:34:43 +0000 | [diff] [blame] | 184 | 		i++; | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 185 | 		*ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1; | 
| Jack Jansen | d26b458 | 1993-01-22 15:34:43 +0000 | [diff] [blame] | 186 | 	    } | 
 | 187 | 	} | 
 | 188 |     } | 
 | 189 |     return rv; | 
 | 190 | } | 
 | 191 |  | 
| Guido van Rossum | 5f59d60 | 1992-12-14 16:59:51 +0000 | [diff] [blame] | 192 | static object * | 
 | 193 | imageop_grey2mono(self, args) | 
 | 194 |     object *self; | 
 | 195 |     object *args; | 
 | 196 | { | 
 | 197 |     int tres, x, y, len; | 
 | 198 |     unsigned char *cp, *ncp; | 
 | 199 |     unsigned char ovalue; | 
 | 200 |     object *rv; | 
 | 201 |     int i, bit; | 
 | 202 |     | 
 | 203 |      | 
 | 204 |     if ( !getargs(args, "(s#iii)", &cp, &len, &x, &y, &tres) ) | 
 | 205 |       return 0; | 
 | 206 |  | 
 | 207 |     if ( x*y != len ) { | 
 | 208 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 209 | 	return 0; | 
 | 210 |     } | 
 | 211 |      | 
 | 212 |     rv = newsizedstringobject(NULL, (len+7)/8); | 
 | 213 |     if ( rv == 0 ) | 
 | 214 |       return 0; | 
 | 215 |     ncp = (unsigned char *)getstringvalue(rv); | 
 | 216 |  | 
 | 217 |     bit = 0x80; | 
 | 218 |     ovalue = 0; | 
 | 219 |     for ( i=0; i < len; i++ ) { | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 220 | 	if ( (int)cp[i] > tres ) | 
| Guido van Rossum | 5f59d60 | 1992-12-14 16:59:51 +0000 | [diff] [blame] | 221 | 	  ovalue |= bit; | 
 | 222 | 	bit >>= 1; | 
 | 223 | 	if ( bit == 0 ) { | 
 | 224 | 	    *ncp++ = ovalue; | 
 | 225 | 	    bit = 0x80; | 
 | 226 | 	    ovalue = 0; | 
 | 227 | 	} | 
 | 228 |     } | 
 | 229 |     if ( bit != 0x80 ) | 
 | 230 |       *ncp++ = ovalue; | 
 | 231 |     return rv; | 
 | 232 | } | 
 | 233 |  | 
 | 234 | static object * | 
| Jack Jansen | de3adf9 | 1992-12-22 14:05:55 +0000 | [diff] [blame] | 235 | imageop_grey2grey4(self, args) | 
 | 236 |     object *self; | 
 | 237 |     object *args; | 
 | 238 | { | 
 | 239 |     int x, y, len; | 
 | 240 |     unsigned char *cp, *ncp; | 
 | 241 |     unsigned char ovalue; | 
 | 242 |     object *rv; | 
 | 243 |     int i; | 
 | 244 |     int pos; | 
 | 245 |     | 
 | 246 |      | 
 | 247 |     if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) ) | 
 | 248 |       return 0; | 
 | 249 |  | 
 | 250 |     if ( x*y != len ) { | 
 | 251 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 252 | 	return 0; | 
 | 253 |     } | 
 | 254 |      | 
 | 255 |     rv = newsizedstringobject(NULL, (len+1)/2); | 
 | 256 |     if ( rv == 0 ) | 
 | 257 |       return 0; | 
 | 258 |     ncp = (unsigned char *)getstringvalue(rv); | 
 | 259 |     pos = 0; | 
 | 260 |     ovalue = 0; | 
 | 261 |     for ( i=0; i < len; i++ ) { | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 262 | 	ovalue |= ((int)cp[i] & 0xf0) >> pos; | 
| Jack Jansen | de3adf9 | 1992-12-22 14:05:55 +0000 | [diff] [blame] | 263 | 	pos += 4; | 
 | 264 | 	if ( pos == 8 ) { | 
 | 265 | 	    *ncp++ = ovalue; | 
 | 266 | 	    ovalue = 0; | 
 | 267 | 	    pos = 0; | 
 | 268 | 	} | 
 | 269 |     } | 
 | 270 |     if ( pos != 0 ) | 
 | 271 |       *ncp++ = ovalue; | 
 | 272 |     return rv; | 
 | 273 | } | 
 | 274 |  | 
 | 275 | static object * | 
 | 276 | imageop_grey2grey2(self, args) | 
 | 277 |     object *self; | 
 | 278 |     object *args; | 
 | 279 | { | 
 | 280 |     int x, y, len; | 
 | 281 |     unsigned char *cp, *ncp; | 
 | 282 |     unsigned char ovalue; | 
 | 283 |     object *rv; | 
 | 284 |     int i; | 
 | 285 |     int pos; | 
 | 286 |     | 
 | 287 |      | 
 | 288 |     if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) ) | 
 | 289 |       return 0; | 
 | 290 |  | 
 | 291 |     if ( x*y != len ) { | 
 | 292 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 293 | 	return 0; | 
 | 294 |     } | 
 | 295 |      | 
 | 296 |     rv = newsizedstringobject(NULL, (len+3)/4); | 
 | 297 |     if ( rv == 0 ) | 
 | 298 |       return 0; | 
 | 299 |     ncp = (unsigned char *)getstringvalue(rv); | 
 | 300 |     pos = 0; | 
 | 301 |     ovalue = 0; | 
 | 302 |     for ( i=0; i < len; i++ ) { | 
| Guido van Rossum | b6775db | 1994-08-01 11:34:53 +0000 | [diff] [blame] | 303 | 	ovalue |= ((int)cp[i] & 0xc0) >> pos; | 
| Jack Jansen | de3adf9 | 1992-12-22 14:05:55 +0000 | [diff] [blame] | 304 | 	pos += 2; | 
 | 305 | 	if ( pos == 8 ) { | 
 | 306 | 	    *ncp++ = ovalue; | 
 | 307 | 	    ovalue = 0; | 
 | 308 | 	    pos = 0; | 
 | 309 | 	} | 
 | 310 |     } | 
 | 311 |     if ( pos != 0 ) | 
 | 312 |       *ncp++ = ovalue; | 
 | 313 |     return rv; | 
 | 314 | } | 
 | 315 |  | 
 | 316 | static object * | 
| Guido van Rossum | 5f59d60 | 1992-12-14 16:59:51 +0000 | [diff] [blame] | 317 | imageop_dither2mono(self, args) | 
 | 318 |     object *self; | 
 | 319 |     object *args; | 
 | 320 | { | 
 | 321 |     int sum, x, y, len; | 
 | 322 |     unsigned char *cp, *ncp; | 
 | 323 |     unsigned char ovalue; | 
 | 324 |     object *rv; | 
 | 325 |     int i, bit; | 
 | 326 |     | 
 | 327 |      | 
 | 328 |     if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) ) | 
 | 329 |       return 0; | 
 | 330 |  | 
 | 331 |     if ( x*y != len ) { | 
 | 332 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 333 | 	return 0; | 
 | 334 |     } | 
 | 335 |      | 
 | 336 |     rv = newsizedstringobject(NULL, (len+7)/8); | 
 | 337 |     if ( rv == 0 ) | 
 | 338 |       return 0; | 
 | 339 |     ncp = (unsigned char *)getstringvalue(rv); | 
 | 340 |  | 
 | 341 |     bit = 0x80; | 
 | 342 |     ovalue = 0; | 
 | 343 |     sum = 0; | 
 | 344 |     for ( i=0; i < len; i++ ) { | 
 | 345 | 	sum += cp[i]; | 
 | 346 | 	if ( sum >= 256 ) { | 
 | 347 | 	    sum -= 256; | 
 | 348 | 	    ovalue |= bit; | 
 | 349 | 	} | 
 | 350 | 	bit >>= 1; | 
 | 351 | 	if ( bit == 0 ) { | 
 | 352 | 	    *ncp++ = ovalue; | 
 | 353 | 	    bit = 0x80; | 
 | 354 | 	    ovalue = 0; | 
 | 355 | 	} | 
 | 356 |     } | 
 | 357 |     if ( bit != 0x80 ) | 
 | 358 |       *ncp++ = ovalue; | 
 | 359 |     return rv; | 
 | 360 | } | 
 | 361 |  | 
 | 362 | static object * | 
| Jack Jansen | de3adf9 | 1992-12-22 14:05:55 +0000 | [diff] [blame] | 363 | imageop_dither2grey2(self, args) | 
 | 364 |     object *self; | 
 | 365 |     object *args; | 
 | 366 | { | 
 | 367 |     int x, y, len; | 
 | 368 |     unsigned char *cp, *ncp; | 
 | 369 |     unsigned char ovalue; | 
 | 370 |     object *rv; | 
 | 371 |     int i; | 
 | 372 |     int pos; | 
| Jack Jansen | 44fff3c | 1994-12-14 12:55:17 +0000 | [diff] [blame] | 373 |     int sum = 0, nvalue; | 
| Jack Jansen | de3adf9 | 1992-12-22 14:05:55 +0000 | [diff] [blame] | 374 |     | 
 | 375 |      | 
 | 376 |     if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) ) | 
 | 377 |       return 0; | 
 | 378 |  | 
 | 379 |     if ( x*y != len ) { | 
 | 380 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 381 | 	return 0; | 
 | 382 |     } | 
 | 383 |      | 
 | 384 |     rv = newsizedstringobject(NULL, (len+3)/4); | 
 | 385 |     if ( rv == 0 ) | 
 | 386 |       return 0; | 
 | 387 |     ncp = (unsigned char *)getstringvalue(rv); | 
 | 388 |     pos = 1; | 
 | 389 |     ovalue = 0; | 
 | 390 |     for ( i=0; i < len; i++ ) { | 
 | 391 | 	sum += cp[i]; | 
 | 392 | 	nvalue = sum & 0x180; | 
 | 393 | 	sum -= nvalue; | 
 | 394 | 	ovalue |= nvalue >> pos; | 
 | 395 | 	pos += 2; | 
 | 396 | 	if ( pos == 9 ) { | 
 | 397 | 	    *ncp++ = ovalue; | 
 | 398 | 	    ovalue = 0; | 
 | 399 | 	    pos = 1; | 
 | 400 | 	} | 
 | 401 |     } | 
 | 402 |     if ( pos != 0 ) | 
 | 403 |       *ncp++ = ovalue; | 
 | 404 |     return rv; | 
 | 405 | } | 
 | 406 |  | 
 | 407 | static object * | 
| Guido van Rossum | 5f59d60 | 1992-12-14 16:59:51 +0000 | [diff] [blame] | 408 | imageop_mono2grey(self, args) | 
 | 409 |     object *self; | 
 | 410 |     object *args; | 
 | 411 | { | 
 | 412 |     int v0, v1, x, y, len, nlen; | 
 | 413 |     unsigned char *cp, *ncp; | 
| Guido van Rossum | 5f59d60 | 1992-12-14 16:59:51 +0000 | [diff] [blame] | 414 |     object *rv; | 
| Guido van Rossum | 3bbc62e | 1995-01-02 19:30:30 +0000 | [diff] [blame] | 415 |     int i, bit; | 
| Guido van Rossum | 5f59d60 | 1992-12-14 16:59:51 +0000 | [diff] [blame] | 416 |      | 
 | 417 |     if ( !getargs(args, "(s#iiii)", &cp, &len, &x, &y, &v0, &v1) ) | 
 | 418 |       return 0; | 
 | 419 |  | 
 | 420 |     nlen = x*y; | 
 | 421 |     if ( (nlen+7)/8 != len ) { | 
 | 422 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 423 | 	return 0; | 
 | 424 |     } | 
 | 425 |      | 
 | 426 |     rv = newsizedstringobject(NULL, nlen); | 
 | 427 |     if ( rv == 0 ) | 
 | 428 |       return 0; | 
 | 429 |     ncp = (unsigned char *)getstringvalue(rv); | 
 | 430 |  | 
 | 431 |     bit = 0x80; | 
 | 432 |     for ( i=0; i < nlen; i++ ) { | 
 | 433 | 	if ( *cp & bit ) | 
 | 434 | 	  *ncp++ = v1; | 
 | 435 | 	else | 
 | 436 | 	  *ncp++ = v0; | 
 | 437 | 	bit >>= 1; | 
 | 438 | 	if ( bit == 0 ) { | 
 | 439 | 	    bit = 0x80; | 
 | 440 | 	    cp++; | 
 | 441 | 	} | 
 | 442 |     } | 
 | 443 |     return rv; | 
 | 444 | } | 
 | 445 |  | 
| Jack Jansen | de3adf9 | 1992-12-22 14:05:55 +0000 | [diff] [blame] | 446 | static object * | 
 | 447 | imageop_grey22grey(self, args) | 
 | 448 |     object *self; | 
 | 449 |     object *args; | 
 | 450 | { | 
 | 451 |     int x, y, len, nlen; | 
 | 452 |     unsigned char *cp, *ncp; | 
| Jack Jansen | de3adf9 | 1992-12-22 14:05:55 +0000 | [diff] [blame] | 453 |     object *rv; | 
 | 454 |     int i, pos, value, nvalue; | 
 | 455 |      | 
 | 456 |     if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) ) | 
 | 457 |       return 0; | 
 | 458 |  | 
 | 459 |     nlen = x*y; | 
 | 460 |     if ( (nlen+3)/4 != len ) { | 
 | 461 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 462 | 	return 0; | 
 | 463 |     } | 
 | 464 |      | 
 | 465 |     rv = newsizedstringobject(NULL, nlen); | 
 | 466 |     if ( rv == 0 ) | 
 | 467 |       return 0; | 
 | 468 |     ncp = (unsigned char *)getstringvalue(rv); | 
 | 469 |  | 
 | 470 |     pos = 0; | 
 | 471 |     for ( i=0; i < nlen; i++ ) { | 
 | 472 | 	if ( pos == 0 ) { | 
 | 473 | 	    value = *cp++; | 
 | 474 | 	    pos = 8; | 
 | 475 | 	} | 
 | 476 | 	pos -= 2; | 
 | 477 | 	nvalue = (value >> pos) & 0x03; | 
 | 478 | 	*ncp++ = nvalue | (nvalue << 2) | (nvalue << 4) | (nvalue << 6); | 
 | 479 |     } | 
 | 480 |     return rv; | 
 | 481 | } | 
 | 482 |  | 
 | 483 | static object * | 
 | 484 | imageop_grey42grey(self, args) | 
 | 485 |     object *self; | 
 | 486 |     object *args; | 
 | 487 | { | 
 | 488 |     int x, y, len, nlen; | 
 | 489 |     unsigned char *cp, *ncp; | 
| Jack Jansen | de3adf9 | 1992-12-22 14:05:55 +0000 | [diff] [blame] | 490 |     object *rv; | 
 | 491 |     int i, pos, value, nvalue; | 
 | 492 |      | 
 | 493 |     if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) ) | 
 | 494 |       return 0; | 
 | 495 |  | 
 | 496 |     nlen = x*y; | 
 | 497 |     if ( (nlen+1)/2 != len ) { | 
 | 498 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 499 | 	return 0; | 
 | 500 |     } | 
 | 501 |      | 
 | 502 |     rv = newsizedstringobject(NULL, nlen); | 
 | 503 |     if ( rv == 0 ) | 
 | 504 |       return 0; | 
 | 505 |     ncp = (unsigned char *)getstringvalue(rv); | 
 | 506 |  | 
 | 507 |     pos = 0; | 
 | 508 |     for ( i=0; i < nlen; i++ ) { | 
 | 509 | 	if ( pos == 0 ) { | 
 | 510 | 	    value = *cp++; | 
 | 511 | 	    pos = 8; | 
 | 512 | 	} | 
 | 513 | 	pos -= 4; | 
 | 514 | 	nvalue = (value >> pos) & 0x0f; | 
 | 515 | 	*ncp++ = nvalue | (nvalue << 4); | 
 | 516 |     } | 
 | 517 |     return rv; | 
 | 518 | } | 
 | 519 |  | 
| Jack Jansen | 4fada9c | 1993-02-19 15:51:41 +0000 | [diff] [blame] | 520 | static object * | 
 | 521 | imageop_rgb2rgb8(self, args) | 
 | 522 |     object *self; | 
 | 523 |     object *args; | 
 | 524 | { | 
 | 525 |     int x, y, len, nlen; | 
 | 526 |     unsigned long *cp; | 
 | 527 |     unsigned char *ncp; | 
 | 528 |     object *rv; | 
 | 529 |     int i, r, g, b; | 
 | 530 |     unsigned long value, nvalue; | 
 | 531 |      | 
 | 532 |     if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) ) | 
 | 533 |       return 0; | 
 | 534 |  | 
 | 535 |     nlen = x*y; | 
 | 536 |     if ( nlen*4 != len ) { | 
 | 537 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 538 | 	return 0; | 
 | 539 |     } | 
 | 540 |      | 
 | 541 |     rv = newsizedstringobject(NULL, nlen); | 
 | 542 |     if ( rv == 0 ) | 
 | 543 |       return 0; | 
 | 544 |     ncp = (unsigned char *)getstringvalue(rv); | 
 | 545 |  | 
 | 546 |     for ( i=0; i < nlen; i++ ) { | 
 | 547 | 	/* Bits in source: aaaaaaaa BBbbbbbb GGGggggg RRRrrrrr */ | 
 | 548 | 	value = *cp++; | 
| Sjoerd Mullender | a9c3c22 | 1993-10-11 12:54:31 +0000 | [diff] [blame] | 549 | #if 0 | 
| Jack Jansen | 4fada9c | 1993-02-19 15:51:41 +0000 | [diff] [blame] | 550 | 	r = (value >>  5) & 7; | 
 | 551 | 	g = (value >> 13) & 7; | 
 | 552 | 	b = (value >> 22) & 3; | 
| Sjoerd Mullender | a9c3c22 | 1993-10-11 12:54:31 +0000 | [diff] [blame] | 553 | #else | 
 | 554 | 	r = (int) ((value & 0xff) / 255. * 7. + .5); | 
 | 555 | 	g = (int) (((value >> 8) & 0xff) / 255. * 7. + .5); | 
 | 556 | 	b = (int) (((value >> 16) & 0xff) / 255. * 3. + .5); | 
 | 557 | #endif | 
| Jack Jansen | 4fada9c | 1993-02-19 15:51:41 +0000 | [diff] [blame] | 558 | 	nvalue = (r<<5) | (b<<3) | g; | 
 | 559 | 	*ncp++ = nvalue; | 
 | 560 |     } | 
 | 561 |     return rv; | 
 | 562 | } | 
 | 563 |  | 
 | 564 | static object * | 
 | 565 | imageop_rgb82rgb(self, args) | 
 | 566 |     object *self; | 
 | 567 |     object *args; | 
 | 568 | { | 
 | 569 |     int x, y, len, nlen; | 
 | 570 |     unsigned char *cp; | 
 | 571 |     unsigned long *ncp; | 
 | 572 |     object *rv; | 
 | 573 |     int i, r, g, b; | 
 | 574 |     unsigned long value, nvalue; | 
 | 575 |      | 
 | 576 |     if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) ) | 
 | 577 |       return 0; | 
 | 578 |  | 
 | 579 |     nlen = x*y; | 
 | 580 |     if ( nlen != len ) { | 
 | 581 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 582 | 	return 0; | 
 | 583 |     } | 
 | 584 |      | 
 | 585 |     rv = newsizedstringobject(NULL, nlen*4); | 
 | 586 |     if ( rv == 0 ) | 
 | 587 |       return 0; | 
 | 588 |     ncp = (unsigned long *)getstringvalue(rv); | 
 | 589 |  | 
 | 590 |     for ( i=0; i < nlen; i++ ) { | 
 | 591 | 	/* Bits in source: RRRBBGGG | 
 | 592 | 	** Red and Green are multiplied by 36.5, Blue by 85 | 
 | 593 | 	*/ | 
 | 594 | 	value = *cp++; | 
 | 595 | 	r = (value >> 5) & 7; | 
 | 596 | 	g = (value     ) & 7; | 
 | 597 | 	b = (value >> 3) & 3; | 
 | 598 | 	r = (r<<5) | (r<<3) | (r>>1); | 
 | 599 | 	g = (g<<5) | (g<<3) | (g>>1); | 
 | 600 | 	b = (b<<6) | (b<<4) | (b<<2) | b; | 
 | 601 | 	nvalue = r | (g<<8) | (b<<16); | 
 | 602 | 	*ncp++ = nvalue; | 
 | 603 |     } | 
 | 604 |     return rv; | 
 | 605 | } | 
 | 606 |  | 
 | 607 | static object * | 
 | 608 | imageop_rgb2grey(self, args) | 
 | 609 |     object *self; | 
 | 610 |     object *args; | 
 | 611 | { | 
 | 612 |     int x, y, len, nlen; | 
 | 613 |     unsigned long *cp; | 
 | 614 |     unsigned char *ncp; | 
 | 615 |     object *rv; | 
 | 616 |     int i, r, g, b; | 
 | 617 |     unsigned long value, nvalue; | 
 | 618 |      | 
 | 619 |     if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) ) | 
 | 620 |       return 0; | 
 | 621 |  | 
 | 622 |     nlen = x*y; | 
 | 623 |     if ( nlen*4 != len ) { | 
 | 624 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 625 | 	return 0; | 
 | 626 |     } | 
 | 627 |      | 
 | 628 |     rv = newsizedstringobject(NULL, nlen); | 
 | 629 |     if ( rv == 0 ) | 
 | 630 |       return 0; | 
 | 631 |     ncp = (unsigned char *)getstringvalue(rv); | 
 | 632 |  | 
 | 633 |     for ( i=0; i < nlen; i++ ) { | 
 | 634 | 	value = *cp++; | 
 | 635 | 	r = (value      ) & 0xff; | 
 | 636 | 	g = (value >>  8) & 0xff; | 
 | 637 | 	b = (value >> 16) & 0xff; | 
 | 638 | 	nvalue = (int)(0.30*r + 0.59*g + 0.11*b); | 
 | 639 | 	if ( nvalue > 255 ) nvalue = 255; | 
 | 640 | 	*ncp++ = nvalue; | 
 | 641 |     } | 
 | 642 |     return rv; | 
 | 643 | } | 
 | 644 |  | 
 | 645 | static object * | 
 | 646 | imageop_grey2rgb(self, args) | 
 | 647 |     object *self; | 
 | 648 |     object *args; | 
 | 649 | { | 
 | 650 |     int x, y, len, nlen; | 
 | 651 |     unsigned char *cp; | 
 | 652 |     unsigned long *ncp; | 
 | 653 |     object *rv; | 
 | 654 |     int i; | 
 | 655 |     unsigned long value; | 
 | 656 |      | 
 | 657 |     if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) ) | 
 | 658 |       return 0; | 
 | 659 |  | 
 | 660 |     nlen = x*y; | 
 | 661 |     if ( nlen != len ) { | 
 | 662 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 663 | 	return 0; | 
 | 664 |     } | 
 | 665 |      | 
 | 666 |     rv = newsizedstringobject(NULL, nlen*4); | 
 | 667 |     if ( rv == 0 ) | 
 | 668 |       return 0; | 
 | 669 |     ncp = (unsigned long *)getstringvalue(rv); | 
 | 670 |  | 
 | 671 |     for ( i=0; i < nlen; i++ ) { | 
 | 672 | 	value = *cp++; | 
 | 673 | 	*ncp++ = value | (value << 8 ) | (value << 16); | 
 | 674 |     } | 
 | 675 |     return rv; | 
 | 676 | } | 
 | 677 |  | 
| Guido van Rossum | 0317a47 | 1992-10-26 13:40:15 +0000 | [diff] [blame] | 678 | /* | 
 | 679 | static object * | 
 | 680 | imageop_mul(self, args) | 
 | 681 |     object *self; | 
 | 682 |     object *args; | 
 | 683 | { | 
 | 684 |     char *cp, *ncp; | 
 | 685 |     int len, size, x, y; | 
 | 686 |     object *rv; | 
 | 687 |     int i; | 
 | 688 |  | 
 | 689 |     if ( !getargs(args, "(s#iii)", &cp, &len, &size, &x, &y) ) | 
 | 690 |       return 0; | 
 | 691 |      | 
 | 692 |     if ( size != 1 && size != 4 ) { | 
 | 693 | 	err_setstr(ImageopError, "Size should be 1 or 4"); | 
 | 694 | 	return 0; | 
 | 695 |     } | 
 | 696 |     if ( len != size*x*y ) { | 
 | 697 | 	err_setstr(ImageopError, "String has incorrect length"); | 
 | 698 | 	return 0; | 
 | 699 |     } | 
 | 700 |      | 
 | 701 |     rv = newsizedstringobject(NULL, XXXX); | 
 | 702 |     if ( rv == 0 ) | 
 | 703 |       return 0; | 
 | 704 |     ncp = (char *)getstringvalue(rv); | 
 | 705 |      | 
 | 706 |      | 
 | 707 |     for ( i=0; i < len; i += size ) { | 
 | 708 |     } | 
 | 709 |     return rv; | 
 | 710 | } | 
 | 711 | */ | 
 | 712 |  | 
 | 713 | static struct methodlist imageop_methods[] = { | 
 | 714 |     { "crop",		imageop_crop }, | 
 | 715 |     { "scale",		imageop_scale }, | 
| Guido van Rossum | 5f59d60 | 1992-12-14 16:59:51 +0000 | [diff] [blame] | 716 |     { "grey2mono",	imageop_grey2mono }, | 
| Jack Jansen | de3adf9 | 1992-12-22 14:05:55 +0000 | [diff] [blame] | 717 |     { "grey2grey2",	imageop_grey2grey2 }, | 
 | 718 |     { "grey2grey4",	imageop_grey2grey4 }, | 
| Guido van Rossum | 5f59d60 | 1992-12-14 16:59:51 +0000 | [diff] [blame] | 719 |     { "dither2mono",	imageop_dither2mono }, | 
| Jack Jansen | de3adf9 | 1992-12-22 14:05:55 +0000 | [diff] [blame] | 720 |     { "dither2grey2",	imageop_dither2grey2 }, | 
| Guido van Rossum | 5f59d60 | 1992-12-14 16:59:51 +0000 | [diff] [blame] | 721 |     { "mono2grey",	imageop_mono2grey }, | 
| Jack Jansen | de3adf9 | 1992-12-22 14:05:55 +0000 | [diff] [blame] | 722 |     { "grey22grey",	imageop_grey22grey }, | 
 | 723 |     { "grey42grey",	imageop_grey42grey }, | 
| Jack Jansen | d26b458 | 1993-01-22 15:34:43 +0000 | [diff] [blame] | 724 |     { "tovideo",	imageop_tovideo }, | 
| Jack Jansen | 4fada9c | 1993-02-19 15:51:41 +0000 | [diff] [blame] | 725 |     { "rgb2rgb8",	imageop_rgb2rgb8 }, | 
 | 726 |     { "rgb82rgb",	imageop_rgb82rgb }, | 
 | 727 |     { "rgb2grey",	imageop_rgb2grey }, | 
 | 728 |     { "grey2rgb",	imageop_grey2rgb }, | 
| Guido van Rossum | 0317a47 | 1992-10-26 13:40:15 +0000 | [diff] [blame] | 729 |     { 0,          0 } | 
 | 730 | }; | 
 | 731 |  | 
 | 732 |  | 
 | 733 | void | 
 | 734 | initimageop() | 
 | 735 | { | 
 | 736 | 	object *m, *d; | 
 | 737 | 	m = initmodule("imageop", imageop_methods); | 
 | 738 | 	d = getmoduledict(m); | 
 | 739 | 	ImageopError = newstringobject("imageop.error"); | 
 | 740 | 	if ( ImageopError == NULL || dictinsert(d,"error",ImageopError) ) | 
 | 741 | 	    fatal("can't define imageop.error"); | 
 | 742 | } |