|
1 |
|
2 /* imageopmodule - Various operations on pictures */ |
|
3 |
|
4 #ifdef sun |
|
5 #define signed |
|
6 #endif |
|
7 |
|
8 #include "Python.h" |
|
9 |
|
10 #if SIZEOF_INT == 4 |
|
11 typedef int Py_Int32; |
|
12 typedef unsigned int Py_UInt32; |
|
13 #else |
|
14 #if SIZEOF_LONG == 4 |
|
15 typedef long Py_Int32; |
|
16 typedef unsigned long Py_UInt32; |
|
17 #else |
|
18 #error "No 4-byte integral type" |
|
19 #endif |
|
20 #endif |
|
21 |
|
22 #define CHARP(cp, xmax, x, y) ((char *)(cp+y*xmax+x)) |
|
23 #define SHORTP(cp, xmax, x, y) ((short *)(cp+2*(y*xmax+x))) |
|
24 #define LONGP(cp, xmax, x, y) ((Py_Int32 *)(cp+4*(y*xmax+x))) |
|
25 |
|
26 static PyObject *ImageopError; |
|
27 static PyObject *ImageopDict; |
|
28 |
|
29 /** |
|
30 * Check a coordonnate, make sure that (0 < value). |
|
31 * Return 0 on error. |
|
32 */ |
|
33 static int |
|
34 check_coordonnate(int value, const char* name) |
|
35 { |
|
36 if ( 0 < value) |
|
37 return 1; |
|
38 PyErr_Format(PyExc_ValueError, "%s value is negative or nul", name); |
|
39 return 0; |
|
40 } |
|
41 |
|
42 /** |
|
43 * Check integer overflow to make sure that product == x*y*size. |
|
44 * Return 0 on error. |
|
45 */ |
|
46 static int |
|
47 check_multiply_size(int product, int x, const char* xname, int y, const char* yname, int size) |
|
48 { |
|
49 if ( !check_coordonnate(x, xname) ) |
|
50 return 0; |
|
51 if ( !check_coordonnate(y, yname) ) |
|
52 return 0; |
|
53 if ( size == (product / y) / x ) |
|
54 return 1; |
|
55 PyErr_SetString(ImageopError, "String has incorrect length"); |
|
56 return 0; |
|
57 } |
|
58 |
|
59 /** |
|
60 * Check integer overflow to make sure that product == x*y. |
|
61 * Return 0 on error. |
|
62 */ |
|
63 static int |
|
64 check_multiply(int product, int x, int y) |
|
65 { |
|
66 return check_multiply_size(product, x, "x", y, "y", 1); |
|
67 } |
|
68 |
|
69 /* If this function returns true (the default if anything goes wrong), we're |
|
70 behaving in a backward-compatible way with respect to how multi-byte pixels |
|
71 are stored in the strings. The code in this module was originally written |
|
72 for an SGI which is a big-endian system, and so the old code assumed that |
|
73 4-byte integers hold the R, G, and B values in a particular order. |
|
74 However, on little-endian systems the order is reversed, and so not |
|
75 actually compatible with what gl.lrectwrite and imgfile expect. |
|
76 (gl.lrectwrite and imgfile are also SGI-specific, however, it is |
|
77 conceivable that the data handled here comes from or goes to an SGI or that |
|
78 it is otherwise used in the expectation that the byte order in the strings |
|
79 is as specified.) |
|
80 |
|
81 The function returns the value of the module variable |
|
82 "backward_compatible", or 1 if the variable does not exist or is not an |
|
83 int. |
|
84 */ |
|
85 |
|
86 static int |
|
87 imageop_backward_compatible(void) |
|
88 { |
|
89 static PyObject *bcos; |
|
90 PyObject *bco; |
|
91 long rc; |
|
92 |
|
93 if (ImageopDict == NULL) /* "cannot happen" */ |
|
94 return 1; |
|
95 if (bcos == NULL) { |
|
96 /* cache string object for future use */ |
|
97 bcos = PyString_FromString("backward_compatible"); |
|
98 if (bcos == NULL) |
|
99 return 1; |
|
100 } |
|
101 bco = PyDict_GetItem(ImageopDict, bcos); |
|
102 if (bco == NULL) |
|
103 return 1; |
|
104 if (!PyInt_Check(bco)) |
|
105 return 1; |
|
106 rc = PyInt_AsLong(bco); |
|
107 if (PyErr_Occurred()) { |
|
108 /* not an integer, or too large, or something */ |
|
109 PyErr_Clear(); |
|
110 rc = 1; |
|
111 } |
|
112 return rc != 0; /* convert to values 0, 1 */ |
|
113 } |
|
114 |
|
115 static PyObject * |
|
116 imageop_crop(PyObject *self, PyObject *args) |
|
117 { |
|
118 char *cp, *ncp; |
|
119 short *nsp; |
|
120 Py_Int32 *nlp; |
|
121 int len, size, x, y, newx1, newx2, newy1, newy2, nlen; |
|
122 int ix, iy, xstep, ystep; |
|
123 PyObject *rv; |
|
124 |
|
125 if ( !PyArg_ParseTuple(args, "s#iiiiiii", &cp, &len, &size, &x, &y, |
|
126 &newx1, &newy1, &newx2, &newy2) ) |
|
127 return 0; |
|
128 |
|
129 if ( size != 1 && size != 2 && size != 4 ) { |
|
130 PyErr_SetString(ImageopError, "Size should be 1, 2 or 4"); |
|
131 return 0; |
|
132 } |
|
133 if ( !check_multiply_size(len, x, "x", y, "y", size) ) |
|
134 return 0; |
|
135 |
|
136 xstep = (newx1 < newx2)? 1 : -1; |
|
137 ystep = (newy1 < newy2)? 1 : -1; |
|
138 |
|
139 nlen = (abs(newx2-newx1)+1)*(abs(newy2-newy1)+1)*size; |
|
140 if ( !check_multiply_size(nlen, abs(newx2-newx1)+1, "abs(newx2-newx1)+1", abs(newy2-newy1)+1, "abs(newy2-newy1)+1", size) ) |
|
141 return 0; |
|
142 rv = PyString_FromStringAndSize(NULL, nlen); |
|
143 if ( rv == 0 ) |
|
144 return 0; |
|
145 ncp = (char *)PyString_AsString(rv); |
|
146 nsp = (short *)ncp; |
|
147 nlp = (Py_Int32 *)ncp; |
|
148 newy2 += ystep; |
|
149 newx2 += xstep; |
|
150 for( iy = newy1; iy != newy2; iy+=ystep ) { |
|
151 for ( ix = newx1; ix != newx2; ix+=xstep ) { |
|
152 if ( iy < 0 || iy >= y || ix < 0 || ix >= x ) { |
|
153 if ( size == 1 ) |
|
154 *ncp++ = 0; |
|
155 else |
|
156 *nlp++ = 0; |
|
157 } else { |
|
158 if ( size == 1 ) |
|
159 *ncp++ = *CHARP(cp, x, ix, iy); |
|
160 else if ( size == 2 ) |
|
161 *nsp++ = *SHORTP(cp, x, ix, iy); |
|
162 else |
|
163 *nlp++ = *LONGP(cp, x, ix, iy); |
|
164 } |
|
165 } |
|
166 } |
|
167 return rv; |
|
168 } |
|
169 |
|
170 static PyObject * |
|
171 imageop_scale(PyObject *self, PyObject *args) |
|
172 { |
|
173 char *cp, *ncp; |
|
174 short *nsp; |
|
175 Py_Int32 *nlp; |
|
176 int len, size, x, y, newx, newy, nlen; |
|
177 int ix, iy; |
|
178 int oix, oiy; |
|
179 PyObject *rv; |
|
180 |
|
181 if ( !PyArg_ParseTuple(args, "s#iiiii", |
|
182 &cp, &len, &size, &x, &y, &newx, &newy) ) |
|
183 return 0; |
|
184 |
|
185 if ( size != 1 && size != 2 && size != 4 ) { |
|
186 PyErr_SetString(ImageopError, "Size should be 1, 2 or 4"); |
|
187 return 0; |
|
188 } |
|
189 if ( !check_multiply_size(len, x, "x", y, "y", size) ) |
|
190 return 0; |
|
191 nlen = newx*newy*size; |
|
192 if ( !check_multiply_size(nlen, newx, "newx", newy, "newy", size) ) |
|
193 return 0; |
|
194 |
|
195 rv = PyString_FromStringAndSize(NULL, nlen); |
|
196 if ( rv == 0 ) |
|
197 return 0; |
|
198 ncp = (char *)PyString_AsString(rv); |
|
199 nsp = (short *)ncp; |
|
200 nlp = (Py_Int32 *)ncp; |
|
201 for( iy = 0; iy < newy; iy++ ) { |
|
202 for ( ix = 0; ix < newx; ix++ ) { |
|
203 oix = ix * x / newx; |
|
204 oiy = iy * y / newy; |
|
205 if ( size == 1 ) |
|
206 *ncp++ = *CHARP(cp, x, oix, oiy); |
|
207 else if ( size == 2 ) |
|
208 *nsp++ = *SHORTP(cp, x, oix, oiy); |
|
209 else |
|
210 *nlp++ = *LONGP(cp, x, oix, oiy); |
|
211 } |
|
212 } |
|
213 return rv; |
|
214 } |
|
215 |
|
216 /* Note: this routine can use a bit of optimizing */ |
|
217 |
|
218 static PyObject * |
|
219 imageop_tovideo(PyObject *self, PyObject *args) |
|
220 { |
|
221 int maxx, maxy, x, y, len; |
|
222 int i; |
|
223 unsigned char *cp, *ncp; |
|
224 int width; |
|
225 PyObject *rv; |
|
226 |
|
227 |
|
228 if ( !PyArg_ParseTuple(args, "s#iii", &cp, &len, &width, &maxx, &maxy) ) |
|
229 return 0; |
|
230 |
|
231 if ( width != 1 && width != 4 ) { |
|
232 PyErr_SetString(ImageopError, "Size should be 1 or 4"); |
|
233 return 0; |
|
234 } |
|
235 if ( !check_multiply_size(len, maxx, "max", maxy, "maxy", width) ) |
|
236 return 0; |
|
237 |
|
238 rv = PyString_FromStringAndSize(NULL, len); |
|
239 if ( rv == 0 ) |
|
240 return 0; |
|
241 ncp = (unsigned char *)PyString_AsString(rv); |
|
242 |
|
243 if ( width == 1 ) { |
|
244 memcpy(ncp, cp, maxx); /* Copy first line */ |
|
245 ncp += maxx; |
|
246 for (y=1; y<maxy; y++) { /* Interpolate other lines */ |
|
247 for(x=0; x<maxx; x++) { |
|
248 i = y*maxx + x; |
|
249 *ncp++ = ((int)cp[i] + (int)cp[i-maxx]) >> 1; |
|
250 } |
|
251 } |
|
252 } else { |
|
253 memcpy(ncp, cp, maxx*4); /* Copy first line */ |
|
254 ncp += maxx*4; |
|
255 for (y=1; y<maxy; y++) { /* Interpolate other lines */ |
|
256 for(x=0; x<maxx; x++) { |
|
257 i = (y*maxx + x)*4 + 1; |
|
258 *ncp++ = 0; /* Skip alfa comp */ |
|
259 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1; |
|
260 i++; |
|
261 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1; |
|
262 i++; |
|
263 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1; |
|
264 } |
|
265 } |
|
266 } |
|
267 return rv; |
|
268 } |
|
269 |
|
270 static PyObject * |
|
271 imageop_grey2mono(PyObject *self, PyObject *args) |
|
272 { |
|
273 int tres, x, y, len; |
|
274 unsigned char *cp, *ncp; |
|
275 unsigned char ovalue; |
|
276 PyObject *rv; |
|
277 int i, bit; |
|
278 |
|
279 |
|
280 if ( !PyArg_ParseTuple(args, "s#iii", &cp, &len, &x, &y, &tres) ) |
|
281 return 0; |
|
282 |
|
283 if ( !check_multiply(len, x, y) ) |
|
284 return 0; |
|
285 |
|
286 rv = PyString_FromStringAndSize(NULL, (len+7)/8); |
|
287 if ( rv == 0 ) |
|
288 return 0; |
|
289 ncp = (unsigned char *)PyString_AsString(rv); |
|
290 |
|
291 bit = 0x80; |
|
292 ovalue = 0; |
|
293 for ( i=0; i < len; i++ ) { |
|
294 if ( (int)cp[i] > tres ) |
|
295 ovalue |= bit; |
|
296 bit >>= 1; |
|
297 if ( bit == 0 ) { |
|
298 *ncp++ = ovalue; |
|
299 bit = 0x80; |
|
300 ovalue = 0; |
|
301 } |
|
302 } |
|
303 if ( bit != 0x80 ) |
|
304 *ncp++ = ovalue; |
|
305 return rv; |
|
306 } |
|
307 |
|
308 static PyObject * |
|
309 imageop_grey2grey4(PyObject *self, PyObject *args) |
|
310 { |
|
311 int x, y, len; |
|
312 unsigned char *cp, *ncp; |
|
313 unsigned char ovalue; |
|
314 PyObject *rv; |
|
315 int i; |
|
316 int pos; |
|
317 |
|
318 |
|
319 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) |
|
320 return 0; |
|
321 |
|
322 if ( !check_multiply(len, x, y) ) |
|
323 return 0; |
|
324 |
|
325 rv = PyString_FromStringAndSize(NULL, (len+1)/2); |
|
326 if ( rv == 0 ) |
|
327 return 0; |
|
328 ncp = (unsigned char *)PyString_AsString(rv); |
|
329 pos = 0; |
|
330 ovalue = 0; |
|
331 for ( i=0; i < len; i++ ) { |
|
332 ovalue |= ((int)cp[i] & 0xf0) >> pos; |
|
333 pos += 4; |
|
334 if ( pos == 8 ) { |
|
335 *ncp++ = ovalue; |
|
336 ovalue = 0; |
|
337 pos = 0; |
|
338 } |
|
339 } |
|
340 if ( pos != 0 ) |
|
341 *ncp++ = ovalue; |
|
342 return rv; |
|
343 } |
|
344 |
|
345 static PyObject * |
|
346 imageop_grey2grey2(PyObject *self, PyObject *args) |
|
347 { |
|
348 int x, y, len; |
|
349 unsigned char *cp, *ncp; |
|
350 unsigned char ovalue; |
|
351 PyObject *rv; |
|
352 int i; |
|
353 int pos; |
|
354 |
|
355 |
|
356 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) |
|
357 return 0; |
|
358 |
|
359 if ( !check_multiply(len, x, y) ) |
|
360 return 0; |
|
361 |
|
362 rv = PyString_FromStringAndSize(NULL, (len+3)/4); |
|
363 if ( rv == 0 ) |
|
364 return 0; |
|
365 ncp = (unsigned char *)PyString_AsString(rv); |
|
366 pos = 0; |
|
367 ovalue = 0; |
|
368 for ( i=0; i < len; i++ ) { |
|
369 ovalue |= ((int)cp[i] & 0xc0) >> pos; |
|
370 pos += 2; |
|
371 if ( pos == 8 ) { |
|
372 *ncp++ = ovalue; |
|
373 ovalue = 0; |
|
374 pos = 0; |
|
375 } |
|
376 } |
|
377 if ( pos != 0 ) |
|
378 *ncp++ = ovalue; |
|
379 return rv; |
|
380 } |
|
381 |
|
382 static PyObject * |
|
383 imageop_dither2mono(PyObject *self, PyObject *args) |
|
384 { |
|
385 int sum, x, y, len; |
|
386 unsigned char *cp, *ncp; |
|
387 unsigned char ovalue; |
|
388 PyObject *rv; |
|
389 int i, bit; |
|
390 |
|
391 |
|
392 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) |
|
393 return 0; |
|
394 |
|
395 if ( !check_multiply(len, x, y) ) |
|
396 return 0; |
|
397 |
|
398 rv = PyString_FromStringAndSize(NULL, (len+7)/8); |
|
399 if ( rv == 0 ) |
|
400 return 0; |
|
401 ncp = (unsigned char *)PyString_AsString(rv); |
|
402 |
|
403 bit = 0x80; |
|
404 ovalue = 0; |
|
405 sum = 0; |
|
406 for ( i=0; i < len; i++ ) { |
|
407 sum += cp[i]; |
|
408 if ( sum >= 256 ) { |
|
409 sum -= 256; |
|
410 ovalue |= bit; |
|
411 } |
|
412 bit >>= 1; |
|
413 if ( bit == 0 ) { |
|
414 *ncp++ = ovalue; |
|
415 bit = 0x80; |
|
416 ovalue = 0; |
|
417 } |
|
418 } |
|
419 if ( bit != 0x80 ) |
|
420 *ncp++ = ovalue; |
|
421 return rv; |
|
422 } |
|
423 |
|
424 static PyObject * |
|
425 imageop_dither2grey2(PyObject *self, PyObject *args) |
|
426 { |
|
427 int x, y, len; |
|
428 unsigned char *cp, *ncp; |
|
429 unsigned char ovalue; |
|
430 PyObject *rv; |
|
431 int i; |
|
432 int pos; |
|
433 int sum = 0, nvalue; |
|
434 |
|
435 |
|
436 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) |
|
437 return 0; |
|
438 |
|
439 if ( !check_multiply(len, x, y) ) |
|
440 return 0; |
|
441 |
|
442 rv = PyString_FromStringAndSize(NULL, (len+3)/4); |
|
443 if ( rv == 0 ) |
|
444 return 0; |
|
445 ncp = (unsigned char *)PyString_AsString(rv); |
|
446 pos = 1; |
|
447 ovalue = 0; |
|
448 for ( i=0; i < len; i++ ) { |
|
449 sum += cp[i]; |
|
450 nvalue = sum & 0x180; |
|
451 sum -= nvalue; |
|
452 ovalue |= nvalue >> pos; |
|
453 pos += 2; |
|
454 if ( pos == 9 ) { |
|
455 *ncp++ = ovalue; |
|
456 ovalue = 0; |
|
457 pos = 1; |
|
458 } |
|
459 } |
|
460 if ( pos != 0 ) |
|
461 *ncp++ = ovalue; |
|
462 return rv; |
|
463 } |
|
464 |
|
465 static PyObject * |
|
466 imageop_mono2grey(PyObject *self, PyObject *args) |
|
467 { |
|
468 int v0, v1, x, y, len, nlen; |
|
469 unsigned char *cp, *ncp; |
|
470 PyObject *rv; |
|
471 int i, bit; |
|
472 |
|
473 if ( !PyArg_ParseTuple(args, "s#iiii", &cp, &len, &x, &y, &v0, &v1) ) |
|
474 return 0; |
|
475 |
|
476 nlen = x*y; |
|
477 if ( !check_multiply(nlen, x, y) ) |
|
478 return 0; |
|
479 if ( (nlen+7)/8 != len ) { |
|
480 PyErr_SetString(ImageopError, "String has incorrect length"); |
|
481 return 0; |
|
482 } |
|
483 |
|
484 rv = PyString_FromStringAndSize(NULL, nlen); |
|
485 if ( rv == 0 ) |
|
486 return 0; |
|
487 ncp = (unsigned char *)PyString_AsString(rv); |
|
488 |
|
489 bit = 0x80; |
|
490 for ( i=0; i < nlen; i++ ) { |
|
491 if ( *cp & bit ) |
|
492 *ncp++ = v1; |
|
493 else |
|
494 *ncp++ = v0; |
|
495 bit >>= 1; |
|
496 if ( bit == 0 ) { |
|
497 bit = 0x80; |
|
498 cp++; |
|
499 } |
|
500 } |
|
501 return rv; |
|
502 } |
|
503 |
|
504 static PyObject * |
|
505 imageop_grey22grey(PyObject *self, PyObject *args) |
|
506 { |
|
507 int x, y, len, nlen; |
|
508 unsigned char *cp, *ncp; |
|
509 PyObject *rv; |
|
510 int i, pos, value = 0, nvalue; |
|
511 |
|
512 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) |
|
513 return 0; |
|
514 |
|
515 nlen = x*y; |
|
516 if ( !check_multiply(nlen, x, y) ) { |
|
517 return 0; |
|
518 } |
|
519 if ( (nlen+3)/4 != len ) { |
|
520 PyErr_SetString(ImageopError, "String has incorrect length"); |
|
521 return 0; |
|
522 } |
|
523 |
|
524 rv = PyString_FromStringAndSize(NULL, nlen); |
|
525 if ( rv == 0 ) |
|
526 return 0; |
|
527 ncp = (unsigned char *)PyString_AsString(rv); |
|
528 |
|
529 pos = 0; |
|
530 for ( i=0; i < nlen; i++ ) { |
|
531 if ( pos == 0 ) { |
|
532 value = *cp++; |
|
533 pos = 8; |
|
534 } |
|
535 pos -= 2; |
|
536 nvalue = (value >> pos) & 0x03; |
|
537 *ncp++ = nvalue | (nvalue << 2) | |
|
538 (nvalue << 4) | (nvalue << 6); |
|
539 } |
|
540 return rv; |
|
541 } |
|
542 |
|
543 static PyObject * |
|
544 imageop_grey42grey(PyObject *self, PyObject *args) |
|
545 { |
|
546 int x, y, len, nlen; |
|
547 unsigned char *cp, *ncp; |
|
548 PyObject *rv; |
|
549 int i, pos, value = 0, nvalue; |
|
550 |
|
551 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) |
|
552 return 0; |
|
553 |
|
554 nlen = x*y; |
|
555 if ( !check_multiply(nlen, x, y) ) |
|
556 return 0; |
|
557 if ( (nlen+1)/2 != len ) { |
|
558 PyErr_SetString(ImageopError, "String has incorrect length"); |
|
559 return 0; |
|
560 } |
|
561 |
|
562 rv = PyString_FromStringAndSize(NULL, nlen); |
|
563 if ( rv == 0 ) |
|
564 return 0; |
|
565 ncp = (unsigned char *)PyString_AsString(rv); |
|
566 |
|
567 pos = 0; |
|
568 for ( i=0; i < nlen; i++ ) { |
|
569 if ( pos == 0 ) { |
|
570 value = *cp++; |
|
571 pos = 8; |
|
572 } |
|
573 pos -= 4; |
|
574 nvalue = (value >> pos) & 0x0f; |
|
575 *ncp++ = nvalue | (nvalue << 4); |
|
576 } |
|
577 return rv; |
|
578 } |
|
579 |
|
580 static PyObject * |
|
581 imageop_rgb2rgb8(PyObject *self, PyObject *args) |
|
582 { |
|
583 int x, y, len, nlen; |
|
584 unsigned char *cp; |
|
585 unsigned char *ncp; |
|
586 PyObject *rv; |
|
587 int i, r, g, b; |
|
588 int backward_compatible = imageop_backward_compatible(); |
|
589 |
|
590 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) |
|
591 return 0; |
|
592 |
|
593 if ( !check_multiply_size(len, x, "x", y, "y", 4) ) |
|
594 return 0; |
|
595 nlen = x*y; |
|
596 if ( !check_multiply(nlen, x, y) ) |
|
597 return 0; |
|
598 |
|
599 rv = PyString_FromStringAndSize(NULL, nlen); |
|
600 if ( rv == 0 ) |
|
601 return 0; |
|
602 ncp = (unsigned char *)PyString_AsString(rv); |
|
603 |
|
604 for ( i=0; i < nlen; i++ ) { |
|
605 /* Bits in source: aaaaaaaa BBbbbbbb GGGggggg RRRrrrrr */ |
|
606 if (backward_compatible) { |
|
607 Py_UInt32 value = * (Py_UInt32 *) cp; |
|
608 cp += 4; |
|
609 r = (int) ((value & 0xff) / 255. * 7. + .5); |
|
610 g = (int) (((value >> 8) & 0xff) / 255. * 7. + .5); |
|
611 b = (int) (((value >> 16) & 0xff) / 255. * 3. + .5); |
|
612 } else { |
|
613 cp++; /* skip alpha channel */ |
|
614 b = (int) (*cp++ / 255. * 3. + .5); |
|
615 g = (int) (*cp++ / 255. * 7. + .5); |
|
616 r = (int) (*cp++ / 255. * 7. + .5); |
|
617 } |
|
618 *ncp++ = (unsigned char)((r<<5) | (b<<3) | g); |
|
619 } |
|
620 return rv; |
|
621 } |
|
622 |
|
623 static PyObject * |
|
624 imageop_rgb82rgb(PyObject *self, PyObject *args) |
|
625 { |
|
626 int x, y, len, nlen; |
|
627 unsigned char *cp; |
|
628 unsigned char *ncp; |
|
629 PyObject *rv; |
|
630 int i, r, g, b; |
|
631 unsigned char value; |
|
632 int backward_compatible = imageop_backward_compatible(); |
|
633 |
|
634 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) |
|
635 return 0; |
|
636 |
|
637 if ( !check_multiply(len, x, y) ) |
|
638 return 0; |
|
639 nlen = x*y*4; |
|
640 if ( !check_multiply_size(nlen, x, "x", y, "y", 4) ) |
|
641 return 0; |
|
642 |
|
643 rv = PyString_FromStringAndSize(NULL, nlen); |
|
644 if ( rv == 0 ) |
|
645 return 0; |
|
646 ncp = (unsigned char *)PyString_AsString(rv); |
|
647 |
|
648 for ( i=0; i < len; i++ ) { |
|
649 /* Bits in source: RRRBBGGG |
|
650 ** Red and Green are multiplied by 36.5, Blue by 85 |
|
651 */ |
|
652 value = *cp++; |
|
653 r = (value >> 5) & 7; |
|
654 g = (value ) & 7; |
|
655 b = (value >> 3) & 3; |
|
656 r = (r<<5) | (r<<3) | (r>>1); |
|
657 g = (g<<5) | (g<<3) | (g>>1); |
|
658 b = (b<<6) | (b<<4) | (b<<2) | b; |
|
659 if (backward_compatible) { |
|
660 Py_UInt32 nvalue = r | (g<<8) | (b<<16); |
|
661 * (Py_UInt32 *) ncp = nvalue; |
|
662 ncp += 4; |
|
663 } else { |
|
664 *ncp++ = 0; |
|
665 *ncp++ = b; |
|
666 *ncp++ = g; |
|
667 *ncp++ = r; |
|
668 } |
|
669 } |
|
670 return rv; |
|
671 } |
|
672 |
|
673 static PyObject * |
|
674 imageop_rgb2grey(PyObject *self, PyObject *args) |
|
675 { |
|
676 int x, y, len, nlen; |
|
677 unsigned char *cp; |
|
678 unsigned char *ncp; |
|
679 PyObject *rv; |
|
680 int i, r, g, b; |
|
681 int nvalue; |
|
682 int backward_compatible = imageop_backward_compatible(); |
|
683 |
|
684 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) |
|
685 return 0; |
|
686 |
|
687 if ( !check_multiply_size(len, x, "x", y, "y", 4) ) |
|
688 return 0; |
|
689 nlen = x*y; |
|
690 if ( !check_multiply(nlen, x, y) ) |
|
691 return 0; |
|
692 |
|
693 rv = PyString_FromStringAndSize(NULL, nlen); |
|
694 if ( rv == 0 ) |
|
695 return 0; |
|
696 ncp = (unsigned char *)PyString_AsString(rv); |
|
697 |
|
698 for ( i=0; i < nlen; i++ ) { |
|
699 if (backward_compatible) { |
|
700 Py_UInt32 value = * (Py_UInt32 *) cp; |
|
701 cp += 4; |
|
702 r = (int) ((value & 0xff) / 255. * 7. + .5); |
|
703 g = (int) (((value >> 8) & 0xff) / 255. * 7. + .5); |
|
704 b = (int) (((value >> 16) & 0xff) / 255. * 3. + .5); |
|
705 } else { |
|
706 cp++; /* skip alpha channel */ |
|
707 b = *cp++; |
|
708 g = *cp++; |
|
709 r = *cp++; |
|
710 } |
|
711 nvalue = (int)(0.30*r + 0.59*g + 0.11*b); |
|
712 if ( nvalue > 255 ) nvalue = 255; |
|
713 *ncp++ = (unsigned char)nvalue; |
|
714 } |
|
715 return rv; |
|
716 } |
|
717 |
|
718 static PyObject * |
|
719 imageop_grey2rgb(PyObject *self, PyObject *args) |
|
720 { |
|
721 int x, y, len, nlen; |
|
722 unsigned char *cp; |
|
723 unsigned char *ncp; |
|
724 PyObject *rv; |
|
725 int i; |
|
726 unsigned char value; |
|
727 int backward_compatible = imageop_backward_compatible(); |
|
728 |
|
729 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) |
|
730 return 0; |
|
731 |
|
732 if ( !check_multiply(len, x, y) ) |
|
733 return 0; |
|
734 nlen = x*y*4; |
|
735 if ( !check_multiply_size(nlen, x, "x", y, "y", 4) ) |
|
736 return 0; |
|
737 |
|
738 rv = PyString_FromStringAndSize(NULL, nlen); |
|
739 if ( rv == 0 ) |
|
740 return 0; |
|
741 ncp = (unsigned char *)PyString_AsString(rv); |
|
742 |
|
743 for ( i=0; i < len; i++ ) { |
|
744 value = *cp++; |
|
745 if (backward_compatible) { |
|
746 * (Py_UInt32 *) ncp = (Py_UInt32) value | ((Py_UInt32) value << 8 ) | ((Py_UInt32) value << 16); |
|
747 ncp += 4; |
|
748 } else { |
|
749 *ncp++ = 0; |
|
750 *ncp++ = value; |
|
751 *ncp++ = value; |
|
752 *ncp++ = value; |
|
753 } |
|
754 } |
|
755 return rv; |
|
756 } |
|
757 |
|
758 static PyMethodDef imageop_methods[] = { |
|
759 { "crop", imageop_crop, METH_VARARGS }, |
|
760 { "scale", imageop_scale, METH_VARARGS }, |
|
761 { "grey2mono", imageop_grey2mono, METH_VARARGS }, |
|
762 { "grey2grey2", imageop_grey2grey2, METH_VARARGS }, |
|
763 { "grey2grey4", imageop_grey2grey4, METH_VARARGS }, |
|
764 { "dither2mono", imageop_dither2mono, METH_VARARGS }, |
|
765 { "dither2grey2", imageop_dither2grey2, METH_VARARGS }, |
|
766 { "mono2grey", imageop_mono2grey, METH_VARARGS }, |
|
767 { "grey22grey", imageop_grey22grey, METH_VARARGS }, |
|
768 { "grey42grey", imageop_grey42grey, METH_VARARGS }, |
|
769 { "tovideo", imageop_tovideo, METH_VARARGS }, |
|
770 { "rgb2rgb8", imageop_rgb2rgb8, METH_VARARGS }, |
|
771 { "rgb82rgb", imageop_rgb82rgb, METH_VARARGS }, |
|
772 { "rgb2grey", imageop_rgb2grey, METH_VARARGS }, |
|
773 { "grey2rgb", imageop_grey2rgb, METH_VARARGS }, |
|
774 { 0, 0 } |
|
775 }; |
|
776 |
|
777 |
|
778 PyMODINIT_FUNC |
|
779 initimageop(void) |
|
780 { |
|
781 PyObject *m; |
|
782 |
|
783 if (PyErr_WarnPy3k("the imageop module has been removed in " |
|
784 "Python 3.0", 2) < 0) |
|
785 return; |
|
786 |
|
787 m = Py_InitModule("imageop", imageop_methods); |
|
788 if (m == NULL) |
|
789 return; |
|
790 ImageopDict = PyModule_GetDict(m); |
|
791 ImageopError = PyErr_NewException("imageop.error", NULL, NULL); |
|
792 if (ImageopError != NULL) |
|
793 PyDict_SetItemString(ImageopDict, "error", ImageopError); |
|
794 } |