blob: 0f3024683c47d4185dc59477a08ec75177181d7f [file] [log] [blame]
Guido van Rossum0317a471992-10-26 13:40:15 +00001/***********************************************************
2Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF 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))
35#define LONGP(cp, xmax, x, y) ((long *)(cp+4*(y*xmax+x)))
36
37static object *ImageopError;
38
39static object *
40imageop_crop(self, args)
41 object *self;
42 object *args;
43{
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;
49
50 if ( !getargs(args, "(s#iiiiiii)", &cp, &len, &size, &x, &y,
51 &newx1, &newy1, &newx2, &newy2) )
52 return 0;
53
54 if ( size != 1 && size != 4 ) {
55 err_setstr(ImageopError, "Size should be 1 or 4");
56 return 0;
57 }
58 if ( len != size*x*y ) {
59 err_setstr(ImageopError, "String has incorrect length");
60 return 0;
61 }
62 xstep = (newx1 < newx2)? 1 : -1;
63 ystep = (newy1 < newy2)? 1 : -1;
64
Guido van Rossum5f59d601992-12-14 16:59:51 +000065 rv = newsizedstringobject(NULL,
66 (abs(newx2-newx1)+1)*(abs(newy2-newy1)+1)*size);
Guido van Rossum0317a471992-10-26 13:40:15 +000067 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);
81 }
82 }
83 }
84 return rv;
85}
86
87static object *
88imageop_scale(self, args)
89 object *self;
90 object *args;
91{
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;
98
99 if ( !getargs(args, "(s#iiiii)", &cp, &len, &size, &x, &y, &newx, &newy) )
100 return 0;
101
102 if ( size != 1 && size != 4 ) {
103 err_setstr(ImageopError, "Size should be 1 or 4");
104 return 0;
105 }
106 if ( len != size*x*y ) {
107 err_setstr(ImageopError, "String has incorrect length");
108 return 0;
109 }
110
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);
122 }
123 }
124 return rv;
125}
126
Guido van Rossum5f59d601992-12-14 16:59:51 +0000127static object *
128imageop_grey2mono(self, args)
129 object *self;
130 object *args;
131{
132 int tres, x, y, len;
133 unsigned char *cp, *ncp;
134 unsigned char ovalue;
135 object *rv;
136 int i, bit;
137
138
139 if ( !getargs(args, "(s#iii)", &cp, &len, &x, &y, &tres) )
140 return 0;
141
142 if ( x*y != len ) {
143 err_setstr(ImageopError, "String has incorrect length");
144 return 0;
145 }
146
147 rv = newsizedstringobject(NULL, (len+7)/8);
148 if ( rv == 0 )
149 return 0;
150 ncp = (unsigned char *)getstringvalue(rv);
151
152 bit = 0x80;
153 ovalue = 0;
154 for ( i=0; i < len; i++ ) {
155 if ( cp[i] > tres )
156 ovalue |= bit;
157 bit >>= 1;
158 if ( bit == 0 ) {
159 *ncp++ = ovalue;
160 bit = 0x80;
161 ovalue = 0;
162 }
163 }
164 if ( bit != 0x80 )
165 *ncp++ = ovalue;
166 return rv;
167}
168
169static object *
Jack Jansende3adf91992-12-22 14:05:55 +0000170imageop_grey2grey4(self, args)
171 object *self;
172 object *args;
173{
174 int x, y, len;
175 unsigned char *cp, *ncp;
176 unsigned char ovalue;
177 object *rv;
178 int i;
179 int pos;
180
181
182 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
183 return 0;
184
185 if ( x*y != len ) {
186 err_setstr(ImageopError, "String has incorrect length");
187 return 0;
188 }
189
190 rv = newsizedstringobject(NULL, (len+1)/2);
191 if ( rv == 0 )
192 return 0;
193 ncp = (unsigned char *)getstringvalue(rv);
194 pos = 0;
195 ovalue = 0;
196 for ( i=0; i < len; i++ ) {
197 ovalue |= (cp[i] & 0xf0) >> pos;
198 pos += 4;
199 if ( pos == 8 ) {
200 *ncp++ = ovalue;
201 ovalue = 0;
202 pos = 0;
203 }
204 }
205 if ( pos != 0 )
206 *ncp++ = ovalue;
207 return rv;
208}
209
210static object *
211imageop_grey2grey2(self, args)
212 object *self;
213 object *args;
214{
215 int x, y, len;
216 unsigned char *cp, *ncp;
217 unsigned char ovalue;
218 object *rv;
219 int i;
220 int pos;
221
222
223 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
224 return 0;
225
226 if ( x*y != len ) {
227 err_setstr(ImageopError, "String has incorrect length");
228 return 0;
229 }
230
231 rv = newsizedstringobject(NULL, (len+3)/4);
232 if ( rv == 0 )
233 return 0;
234 ncp = (unsigned char *)getstringvalue(rv);
235 pos = 0;
236 ovalue = 0;
237 for ( i=0; i < len; i++ ) {
238 ovalue |= (cp[i] & 0xc0) >> pos;
239 pos += 2;
240 if ( pos == 8 ) {
241 *ncp++ = ovalue;
242 ovalue = 0;
243 pos = 0;
244 }
245 }
246 if ( pos != 0 )
247 *ncp++ = ovalue;
248 return rv;
249}
250
251static object *
Guido van Rossum5f59d601992-12-14 16:59:51 +0000252imageop_dither2mono(self, args)
253 object *self;
254 object *args;
255{
256 int sum, x, y, len;
257 unsigned char *cp, *ncp;
258 unsigned char ovalue;
259 object *rv;
260 int i, bit;
261
262
263 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
264 return 0;
265
266 if ( x*y != len ) {
267 err_setstr(ImageopError, "String has incorrect length");
268 return 0;
269 }
270
271 rv = newsizedstringobject(NULL, (len+7)/8);
272 if ( rv == 0 )
273 return 0;
274 ncp = (unsigned char *)getstringvalue(rv);
275
276 bit = 0x80;
277 ovalue = 0;
278 sum = 0;
279 for ( i=0; i < len; i++ ) {
280 sum += cp[i];
281 if ( sum >= 256 ) {
282 sum -= 256;
283 ovalue |= bit;
284 }
285 bit >>= 1;
286 if ( bit == 0 ) {
287 *ncp++ = ovalue;
288 bit = 0x80;
289 ovalue = 0;
290 }
291 }
292 if ( bit != 0x80 )
293 *ncp++ = ovalue;
294 return rv;
295}
296
297static object *
Jack Jansende3adf91992-12-22 14:05:55 +0000298imageop_dither2grey2(self, args)
299 object *self;
300 object *args;
301{
302 int x, y, len;
303 unsigned char *cp, *ncp;
304 unsigned char ovalue;
305 object *rv;
306 int i;
307 int pos;
308 int sum, nvalue;
309
310
311 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
312 return 0;
313
314 if ( x*y != len ) {
315 err_setstr(ImageopError, "String has incorrect length");
316 return 0;
317 }
318
319 rv = newsizedstringobject(NULL, (len+3)/4);
320 if ( rv == 0 )
321 return 0;
322 ncp = (unsigned char *)getstringvalue(rv);
323 pos = 1;
324 ovalue = 0;
325 for ( i=0; i < len; i++ ) {
326 sum += cp[i];
327 nvalue = sum & 0x180;
328 sum -= nvalue;
329 ovalue |= nvalue >> pos;
330 pos += 2;
331 if ( pos == 9 ) {
332 *ncp++ = ovalue;
333 ovalue = 0;
334 pos = 1;
335 }
336 }
337 if ( pos != 0 )
338 *ncp++ = ovalue;
339 return rv;
340}
341
342static object *
Guido van Rossum5f59d601992-12-14 16:59:51 +0000343imageop_mono2grey(self, args)
344 object *self;
345 object *args;
346{
347 int v0, v1, x, y, len, nlen;
348 unsigned char *cp, *ncp;
349 unsigned char ovalue;
350 object *rv;
351 int i, bit, value;
352
353 if ( !getargs(args, "(s#iiii)", &cp, &len, &x, &y, &v0, &v1) )
354 return 0;
355
356 nlen = x*y;
357 if ( (nlen+7)/8 != len ) {
358 err_setstr(ImageopError, "String has incorrect length");
359 return 0;
360 }
361
362 rv = newsizedstringobject(NULL, nlen);
363 if ( rv == 0 )
364 return 0;
365 ncp = (unsigned char *)getstringvalue(rv);
366
367 bit = 0x80;
368 for ( i=0; i < nlen; i++ ) {
369 if ( *cp & bit )
370 *ncp++ = v1;
371 else
372 *ncp++ = v0;
373 bit >>= 1;
374 if ( bit == 0 ) {
375 bit = 0x80;
376 cp++;
377 }
378 }
379 return rv;
380}
381
Jack Jansende3adf91992-12-22 14:05:55 +0000382static object *
383imageop_grey22grey(self, args)
384 object *self;
385 object *args;
386{
387 int x, y, len, nlen;
388 unsigned char *cp, *ncp;
389 unsigned char ovalue;
390 object *rv;
391 int i, pos, value, nvalue;
392
393 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
394 return 0;
395
396 nlen = x*y;
397 if ( (nlen+3)/4 != len ) {
398 err_setstr(ImageopError, "String has incorrect length");
399 return 0;
400 }
401
402 rv = newsizedstringobject(NULL, nlen);
403 if ( rv == 0 )
404 return 0;
405 ncp = (unsigned char *)getstringvalue(rv);
406
407 pos = 0;
408 for ( i=0; i < nlen; i++ ) {
409 if ( pos == 0 ) {
410 value = *cp++;
411 pos = 8;
412 }
413 pos -= 2;
414 nvalue = (value >> pos) & 0x03;
415 *ncp++ = nvalue | (nvalue << 2) | (nvalue << 4) | (nvalue << 6);
416 }
417 return rv;
418}
419
420static object *
421imageop_grey42grey(self, args)
422 object *self;
423 object *args;
424{
425 int x, y, len, nlen;
426 unsigned char *cp, *ncp;
427 unsigned char ovalue;
428 object *rv;
429 int i, pos, value, nvalue;
430
431 if ( !getargs(args, "(s#ii)", &cp, &len, &x, &y) )
432 return 0;
433
434 nlen = x*y;
435 if ( (nlen+1)/2 != len ) {
436 err_setstr(ImageopError, "String has incorrect length");
437 return 0;
438 }
439
440 rv = newsizedstringobject(NULL, nlen);
441 if ( rv == 0 )
442 return 0;
443 ncp = (unsigned char *)getstringvalue(rv);
444
445 pos = 0;
446 for ( i=0; i < nlen; i++ ) {
447 if ( pos == 0 ) {
448 value = *cp++;
449 pos = 8;
450 }
451 pos -= 4;
452 nvalue = (value >> pos) & 0x0f;
453 *ncp++ = nvalue | (nvalue << 4);
454 }
455 return rv;
456}
457
Guido van Rossum0317a471992-10-26 13:40:15 +0000458/*
459static object *
460imageop_mul(self, args)
461 object *self;
462 object *args;
463{
464 char *cp, *ncp;
465 int len, size, x, y;
466 object *rv;
467 int i;
468
469 if ( !getargs(args, "(s#iii)", &cp, &len, &size, &x, &y) )
470 return 0;
471
472 if ( size != 1 && size != 4 ) {
473 err_setstr(ImageopError, "Size should be 1 or 4");
474 return 0;
475 }
476 if ( len != size*x*y ) {
477 err_setstr(ImageopError, "String has incorrect length");
478 return 0;
479 }
480
481 rv = newsizedstringobject(NULL, XXXX);
482 if ( rv == 0 )
483 return 0;
484 ncp = (char *)getstringvalue(rv);
485
486
487 for ( i=0; i < len; i += size ) {
488 }
489 return rv;
490}
491*/
492
493static struct methodlist imageop_methods[] = {
494 { "crop", imageop_crop },
495 { "scale", imageop_scale },
Guido van Rossum5f59d601992-12-14 16:59:51 +0000496 { "grey2mono", imageop_grey2mono },
Jack Jansende3adf91992-12-22 14:05:55 +0000497 { "grey2grey2", imageop_grey2grey2 },
498 { "grey2grey4", imageop_grey2grey4 },
Guido van Rossum5f59d601992-12-14 16:59:51 +0000499 { "dither2mono", imageop_dither2mono },
Jack Jansende3adf91992-12-22 14:05:55 +0000500 { "dither2grey2", imageop_dither2grey2 },
Guido van Rossum5f59d601992-12-14 16:59:51 +0000501 { "mono2grey", imageop_mono2grey },
Jack Jansende3adf91992-12-22 14:05:55 +0000502 { "grey22grey", imageop_grey22grey },
503 { "grey42grey", imageop_grey42grey },
Guido van Rossum0317a471992-10-26 13:40:15 +0000504 { 0, 0 }
505};
506
507
508void
509initimageop()
510{
511 object *m, *d;
512 m = initmodule("imageop", imageop_methods);
513 d = getmoduledict(m);
514 ImageopError = newstringobject("imageop.error");
515 if ( ImageopError == NULL || dictinsert(d,"error",ImageopError) )
516 fatal("can't define imageop.error");
517}