blob: 8bd11b24c8a6dfc2e1f6e9b03c8271ccabf0ab21 [file] [log] [blame]
Guido van Rossum0317a471992-10-26 13:40:15 +00001
2/* imageopmodule - Various operations on pictures */
3
4#ifdef sun
5#define signed
6#endif
7
Roger E. Massea141f8a1996-12-20 20:50:39 +00008#include "Python.h"
Guido van Rossum0317a471992-10-26 13:40:15 +00009
Guido van Rossum69011961998-04-23 20:23:00 +000010#if SIZEOF_INT == 4
11typedef int Py_Int32;
12typedef unsigned int Py_UInt32;
13#else
14#if SIZEOF_LONG == 4
15typedef long Py_Int32;
16typedef unsigned long Py_UInt32;
17#else
18#error "No 4-byte integral type"
19#endif
20#endif
21
Guido van Rossum0317a471992-10-26 13:40:15 +000022#define CHARP(cp, xmax, x, y) ((char *)(cp+y*xmax+x))
Jack Jansen76c79e91996-01-22 14:55:15 +000023#define SHORTP(cp, xmax, x, y) ((short *)(cp+2*(y*xmax+x)))
Guido van Rossum69011961998-04-23 20:23:00 +000024#define LONGP(cp, xmax, x, y) ((Py_Int32 *)(cp+4*(y*xmax+x)))
Guido van Rossum0317a471992-10-26 13:40:15 +000025
Roger E. Massea141f8a1996-12-20 20:50:39 +000026static PyObject *ImageopError;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +000027static PyObject *ImageopDict;
28
Benjamin Peterson8d77d442008-09-30 01:31:49 +000029/**
30 * Check a coordonnate, make sure that (0 < value).
31 * Return 0 on error.
32 */
33static int
34check_coordonnate(int value, const char* name)
35{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000036 if ( 0 < value)
37 return 1;
38 PyErr_Format(PyExc_ValueError, "%s value is negative or nul", name);
39 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +000040}
41
42/**
43 * Check integer overflow to make sure that product == x*y*size.
44 * Return 0 on error.
45 */
46static int
47check_multiply_size(int product, int x, const char* xname, int y, const char* yname, int size)
48{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000049 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;
Benjamin Peterson8d77d442008-09-30 01:31:49 +000057}
58
59/**
60 * Check integer overflow to make sure that product == x*y.
61 * Return 0 on error.
62 */
63static int
64check_multiply(int product, int x, int y)
65{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000066 return check_multiply_size(product, x, "x", y, "y", 1);
Benjamin Peterson8d77d442008-09-30 01:31:49 +000067}
68
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +000069/* 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
86static int
87imageop_backward_compatible(void)
88{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000089 static PyObject *bcos;
90 PyObject *bco;
91 long rc;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +000092
Antoine Pitrouc83ea132010-05-09 14:46:46 +000093 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 */
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000113}
114
Roger E. Massea141f8a1996-12-20 20:50:39 +0000115static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000116imageop_crop(PyObject *self, PyObject *args)
Guido van Rossum0317a471992-10-26 13:40:15 +0000117{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000118 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;
Guido van Rossum0317a471992-10-26 13:40:15 +0000124
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000125 if ( !PyArg_ParseTuple(args, "s#iiiiiii", &cp, &len, &size, &x, &y,
126 &newx1, &newy1, &newx2, &newy2) )
127 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000128
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000129 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;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000135
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000136 xstep = (newx1 < newx2)? 1 : -1;
137 ystep = (newy1 < newy2)? 1 : -1;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000138
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000139 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;
Guido van Rossum0317a471992-10-26 13:40:15 +0000168}
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000169
Roger E. Massea141f8a1996-12-20 20:50:39 +0000170static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000171imageop_scale(PyObject *self, PyObject *args)
Guido van Rossum0317a471992-10-26 13:40:15 +0000172{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000173 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;
Guido van Rossum0317a471992-10-26 13:40:15 +0000180
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000181 if ( !PyArg_ParseTuple(args, "s#iiiii",
182 &cp, &len, &size, &x, &y, &newx, &newy) )
183 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000184
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000185 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;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000194
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000195 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;
Guido van Rossum0317a471992-10-26 13:40:15 +0000214}
215
Jack Jansend26b4581993-01-22 15:34:43 +0000216/* Note: this routine can use a bit of optimizing */
217
Roger E. Massea141f8a1996-12-20 20:50:39 +0000218static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000219imageop_tovideo(PyObject *self, PyObject *args)
Jack Jansend26b4581993-01-22 15:34:43 +0000220{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000221 int maxx, maxy, x, y, len;
222 int i;
223 unsigned char *cp, *ncp;
224 int width;
225 PyObject *rv;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000226
227
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000228 if ( !PyArg_ParseTuple(args, "s#iii", &cp, &len, &width, &maxx, &maxy) )
229 return 0;
Jack Jansend26b4581993-01-22 15:34:43 +0000230
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000231 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;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000237
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000238 rv = PyString_FromStringAndSize(NULL, len);
239 if ( rv == 0 )
240 return 0;
241 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansend26b4581993-01-22 15:34:43 +0000242
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000243 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;
Jack Jansend26b4581993-01-22 15:34:43 +0000268}
269
Roger E. Massea141f8a1996-12-20 20:50:39 +0000270static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000271imageop_grey2mono(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000272{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000273 int tres, x, y, len;
274 unsigned char *cp, *ncp;
275 unsigned char ovalue;
276 PyObject *rv;
277 int i, bit;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000278
279
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000280 if ( !PyArg_ParseTuple(args, "s#iii", &cp, &len, &x, &y, &tres) )
281 return 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000282
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000283 if ( !check_multiply(len, x, y) )
284 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000285
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000286 rv = PyString_FromStringAndSize(NULL, (len+7)/8);
287 if ( rv == 0 )
288 return 0;
289 ncp = (unsigned char *)PyString_AsString(rv);
Roger E. Massea141f8a1996-12-20 20:50:39 +0000290
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000291 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;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000306}
307
Roger E. Massea141f8a1996-12-20 20:50:39 +0000308static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000309imageop_grey2grey4(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000310{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000311 int x, y, len;
312 unsigned char *cp, *ncp;
313 unsigned char ovalue;
314 PyObject *rv;
315 int i;
316 int pos;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000317
318
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000319 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
320 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000321
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000322 if ( !check_multiply(len, x, y) )
323 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000324
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000325 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;
Jack Jansende3adf91992-12-22 14:05:55 +0000343}
344
Roger E. Massea141f8a1996-12-20 20:50:39 +0000345static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000346imageop_grey2grey2(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000347{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000348 int x, y, len;
349 unsigned char *cp, *ncp;
350 unsigned char ovalue;
351 PyObject *rv;
352 int i;
353 int pos;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000354
355
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000356 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
357 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000358
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000359 if ( !check_multiply(len, x, y) )
360 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000361
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000362 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;
Jack Jansende3adf91992-12-22 14:05:55 +0000380}
381
Roger E. Massea141f8a1996-12-20 20:50:39 +0000382static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000383imageop_dither2mono(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000384{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000385 int sum, x, y, len;
386 unsigned char *cp, *ncp;
387 unsigned char ovalue;
388 PyObject *rv;
389 int i, bit;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000390
391
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000392 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
393 return 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000394
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000395 if ( !check_multiply(len, x, y) )
396 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000397
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000398 rv = PyString_FromStringAndSize(NULL, (len+7)/8);
399 if ( rv == 0 )
400 return 0;
401 ncp = (unsigned char *)PyString_AsString(rv);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000402
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000403 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;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000422}
423
Roger E. Massea141f8a1996-12-20 20:50:39 +0000424static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000425imageop_dither2grey2(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000426{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000427 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;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000434
435
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000436 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
437 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000438
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000439 if ( !check_multiply(len, x, y) )
440 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000441
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000442 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;
Jack Jansende3adf91992-12-22 14:05:55 +0000463}
464
Roger E. Massea141f8a1996-12-20 20:50:39 +0000465static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000466imageop_mono2grey(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000467{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000468 int v0, v1, x, y, len, nlen;
469 unsigned char *cp, *ncp;
470 PyObject *rv;
471 int i, bit;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000472
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000473 if ( !PyArg_ParseTuple(args, "s#iiii", &cp, &len, &x, &y, &v0, &v1) )
474 return 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000475
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000476 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 }
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000483
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000484 rv = PyString_FromStringAndSize(NULL, nlen);
485 if ( rv == 0 )
486 return 0;
487 ncp = (unsigned char *)PyString_AsString(rv);
Roger E. Massea141f8a1996-12-20 20:50:39 +0000488
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000489 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;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000502}
503
Roger E. Massea141f8a1996-12-20 20:50:39 +0000504static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000505imageop_grey22grey(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000506{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000507 int x, y, len, nlen;
508 unsigned char *cp, *ncp;
509 PyObject *rv;
510 int i, pos, value = 0, nvalue;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000511
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000512 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
513 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000514
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000515 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 }
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000523
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000524 rv = PyString_FromStringAndSize(NULL, nlen);
525 if ( rv == 0 )
526 return 0;
527 ncp = (unsigned char *)PyString_AsString(rv);
Roger E. Massea141f8a1996-12-20 20:50:39 +0000528
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000529 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;
Jack Jansende3adf91992-12-22 14:05:55 +0000541}
542
Roger E. Massea141f8a1996-12-20 20:50:39 +0000543static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000544imageop_grey42grey(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000545{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000546 int x, y, len, nlen;
547 unsigned char *cp, *ncp;
548 PyObject *rv;
549 int i, pos, value = 0, nvalue;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000550
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000551 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
552 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000553
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000554 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 }
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000561
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000562 rv = PyString_FromStringAndSize(NULL, nlen);
563 if ( rv == 0 )
564 return 0;
565 ncp = (unsigned char *)PyString_AsString(rv);
Roger E. Massea141f8a1996-12-20 20:50:39 +0000566
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000567 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;
Jack Jansende3adf91992-12-22 14:05:55 +0000578}
579
Roger E. Massea141f8a1996-12-20 20:50:39 +0000580static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000581imageop_rgb2rgb8(PyObject *self, PyObject *args)
Jack Jansen4fada9c1993-02-19 15:51:41 +0000582{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000583 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();
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000589
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000590 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
591 return 0;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000592
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000593 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;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000598
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000599 rv = PyString_FromStringAndSize(NULL, nlen);
600 if ( rv == 0 )
601 return 0;
602 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansen4fada9c1993-02-19 15:51:41 +0000603
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000604 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;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000621}
622
Roger E. Massea141f8a1996-12-20 20:50:39 +0000623static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000624imageop_rgb82rgb(PyObject *self, PyObject *args)
Jack Jansen4fada9c1993-02-19 15:51:41 +0000625{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000626 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();
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000633
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000634 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
635 return 0;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000636
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000637 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;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000642
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000643 rv = PyString_FromStringAndSize(NULL, nlen);
644 if ( rv == 0 )
645 return 0;
646 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansen4fada9c1993-02-19 15:51:41 +0000647
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000648 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;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000671}
672
Roger E. Massea141f8a1996-12-20 20:50:39 +0000673static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000674imageop_rgb2grey(PyObject *self, PyObject *args)
Jack Jansen4fada9c1993-02-19 15:51:41 +0000675{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000676 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();
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000683
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000684 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
685 return 0;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000686
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000687 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;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000692
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000693 rv = PyString_FromStringAndSize(NULL, nlen);
694 if ( rv == 0 )
695 return 0;
696 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansen4fada9c1993-02-19 15:51:41 +0000697
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000698 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;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000716}
717
Roger E. Massea141f8a1996-12-20 20:50:39 +0000718static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000719imageop_grey2rgb(PyObject *self, PyObject *args)
Jack Jansen4fada9c1993-02-19 15:51:41 +0000720{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000721 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();
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000728
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000729 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
730 return 0;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000731
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000732 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;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000737
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000738 rv = PyString_FromStringAndSize(NULL, nlen);
739 if ( rv == 0 )
740 return 0;
741 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansen4fada9c1993-02-19 15:51:41 +0000742
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000743 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;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000756}
757
Roger E. Massea141f8a1996-12-20 20:50:39 +0000758static PyMethodDef imageop_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000759 { "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 }
Guido van Rossum0317a471992-10-26 13:40:15 +0000775};
776
777
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000778PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000779initimageop(void)
Guido van Rossum0317a471992-10-26 13:40:15 +0000780{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000781 PyObject *m;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000782
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000783 if (PyErr_WarnPy3k("the imageop module has been removed in "
784 "Python 3.0", 2) < 0)
785 return;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000786
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000787 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);
Guido van Rossum0317a471992-10-26 13:40:15 +0000794}