blob: b91f967eb2c5bd3c413d5380fb0a953799822d55 [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;
Serhiy Storchaka062bed22015-05-31 09:05:10 +030053 if ( product % y == 0 ) {
54 product /= y;
55 if ( product % x == 0 && size == product / x )
56 return 1;
57 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +000058 PyErr_SetString(ImageopError, "String has incorrect length");
59 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +000060}
61
62/**
63 * Check integer overflow to make sure that product == x*y.
64 * Return 0 on error.
65 */
66static int
67check_multiply(int product, int x, int y)
68{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000069 return check_multiply_size(product, x, "x", y, "y", 1);
Benjamin Peterson8d77d442008-09-30 01:31:49 +000070}
71
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +000072/* If this function returns true (the default if anything goes wrong), we're
73 behaving in a backward-compatible way with respect to how multi-byte pixels
74 are stored in the strings. The code in this module was originally written
75 for an SGI which is a big-endian system, and so the old code assumed that
76 4-byte integers hold the R, G, and B values in a particular order.
77 However, on little-endian systems the order is reversed, and so not
78 actually compatible with what gl.lrectwrite and imgfile expect.
79 (gl.lrectwrite and imgfile are also SGI-specific, however, it is
80 conceivable that the data handled here comes from or goes to an SGI or that
81 it is otherwise used in the expectation that the byte order in the strings
82 is as specified.)
83
84 The function returns the value of the module variable
85 "backward_compatible", or 1 if the variable does not exist or is not an
86 int.
87 */
88
89static int
90imageop_backward_compatible(void)
91{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000092 static PyObject *bcos;
93 PyObject *bco;
94 long rc;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +000095
Antoine Pitrouc83ea132010-05-09 14:46:46 +000096 if (ImageopDict == NULL) /* "cannot happen" */
97 return 1;
98 if (bcos == NULL) {
99 /* cache string object for future use */
100 bcos = PyString_FromString("backward_compatible");
101 if (bcos == NULL)
102 return 1;
103 }
104 bco = PyDict_GetItem(ImageopDict, bcos);
105 if (bco == NULL)
106 return 1;
107 if (!PyInt_Check(bco))
108 return 1;
109 rc = PyInt_AsLong(bco);
110 if (PyErr_Occurred()) {
111 /* not an integer, or too large, or something */
112 PyErr_Clear();
113 rc = 1;
114 }
115 return rc != 0; /* convert to values 0, 1 */
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000116}
117
Roger E. Massea141f8a1996-12-20 20:50:39 +0000118static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000119imageop_crop(PyObject *self, PyObject *args)
Guido van Rossum0317a471992-10-26 13:40:15 +0000120{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000121 char *cp, *ncp;
122 short *nsp;
123 Py_Int32 *nlp;
124 int len, size, x, y, newx1, newx2, newy1, newy2, nlen;
125 int ix, iy, xstep, ystep;
126 PyObject *rv;
Guido van Rossum0317a471992-10-26 13:40:15 +0000127
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000128 if ( !PyArg_ParseTuple(args, "s#iiiiiii", &cp, &len, &size, &x, &y,
129 &newx1, &newy1, &newx2, &newy2) )
130 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000131
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000132 if ( size != 1 && size != 2 && size != 4 ) {
133 PyErr_SetString(ImageopError, "Size should be 1, 2 or 4");
134 return 0;
135 }
136 if ( !check_multiply_size(len, x, "x", y, "y", size) )
137 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000138
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000139 xstep = (newx1 < newx2)? 1 : -1;
140 ystep = (newy1 < newy2)? 1 : -1;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000141
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000142 nlen = (abs(newx2-newx1)+1)*(abs(newy2-newy1)+1)*size;
143 if ( !check_multiply_size(nlen, abs(newx2-newx1)+1, "abs(newx2-newx1)+1", abs(newy2-newy1)+1, "abs(newy2-newy1)+1", size) )
144 return 0;
145 rv = PyString_FromStringAndSize(NULL, nlen);
146 if ( rv == 0 )
147 return 0;
148 ncp = (char *)PyString_AsString(rv);
149 nsp = (short *)ncp;
150 nlp = (Py_Int32 *)ncp;
151 newy2 += ystep;
152 newx2 += xstep;
153 for( iy = newy1; iy != newy2; iy+=ystep ) {
154 for ( ix = newx1; ix != newx2; ix+=xstep ) {
155 if ( iy < 0 || iy >= y || ix < 0 || ix >= x ) {
156 if ( size == 1 )
157 *ncp++ = 0;
158 else
159 *nlp++ = 0;
160 } else {
161 if ( size == 1 )
162 *ncp++ = *CHARP(cp, x, ix, iy);
163 else if ( size == 2 )
164 *nsp++ = *SHORTP(cp, x, ix, iy);
165 else
166 *nlp++ = *LONGP(cp, x, ix, iy);
167 }
168 }
169 }
170 return rv;
Guido van Rossum0317a471992-10-26 13:40:15 +0000171}
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000172
Roger E. Massea141f8a1996-12-20 20:50:39 +0000173static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000174imageop_scale(PyObject *self, PyObject *args)
Guido van Rossum0317a471992-10-26 13:40:15 +0000175{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000176 char *cp, *ncp;
177 short *nsp;
178 Py_Int32 *nlp;
179 int len, size, x, y, newx, newy, nlen;
180 int ix, iy;
181 int oix, oiy;
182 PyObject *rv;
Guido van Rossum0317a471992-10-26 13:40:15 +0000183
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000184 if ( !PyArg_ParseTuple(args, "s#iiiii",
185 &cp, &len, &size, &x, &y, &newx, &newy) )
186 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000187
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000188 if ( size != 1 && size != 2 && size != 4 ) {
189 PyErr_SetString(ImageopError, "Size should be 1, 2 or 4");
190 return 0;
191 }
192 if ( !check_multiply_size(len, x, "x", y, "y", size) )
193 return 0;
194 nlen = newx*newy*size;
195 if ( !check_multiply_size(nlen, newx, "newx", newy, "newy", size) )
196 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000197
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000198 rv = PyString_FromStringAndSize(NULL, nlen);
199 if ( rv == 0 )
200 return 0;
201 ncp = (char *)PyString_AsString(rv);
202 nsp = (short *)ncp;
203 nlp = (Py_Int32 *)ncp;
204 for( iy = 0; iy < newy; iy++ ) {
205 for ( ix = 0; ix < newx; ix++ ) {
206 oix = ix * x / newx;
207 oiy = iy * y / newy;
208 if ( size == 1 )
209 *ncp++ = *CHARP(cp, x, oix, oiy);
210 else if ( size == 2 )
211 *nsp++ = *SHORTP(cp, x, oix, oiy);
212 else
213 *nlp++ = *LONGP(cp, x, oix, oiy);
214 }
215 }
216 return rv;
Guido van Rossum0317a471992-10-26 13:40:15 +0000217}
218
Jack Jansend26b4581993-01-22 15:34:43 +0000219/* Note: this routine can use a bit of optimizing */
220
Roger E. Massea141f8a1996-12-20 20:50:39 +0000221static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000222imageop_tovideo(PyObject *self, PyObject *args)
Jack Jansend26b4581993-01-22 15:34:43 +0000223{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000224 int maxx, maxy, x, y, len;
225 int i;
226 unsigned char *cp, *ncp;
227 int width;
228 PyObject *rv;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000229
230
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000231 if ( !PyArg_ParseTuple(args, "s#iii", &cp, &len, &width, &maxx, &maxy) )
232 return 0;
Jack Jansend26b4581993-01-22 15:34:43 +0000233
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000234 if ( width != 1 && width != 4 ) {
235 PyErr_SetString(ImageopError, "Size should be 1 or 4");
236 return 0;
237 }
238 if ( !check_multiply_size(len, maxx, "max", maxy, "maxy", width) )
239 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000240
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000241 rv = PyString_FromStringAndSize(NULL, len);
242 if ( rv == 0 )
243 return 0;
244 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansend26b4581993-01-22 15:34:43 +0000245
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000246 if ( width == 1 ) {
247 memcpy(ncp, cp, maxx); /* Copy first line */
248 ncp += maxx;
249 for (y=1; y<maxy; y++) { /* Interpolate other lines */
250 for(x=0; x<maxx; x++) {
251 i = y*maxx + x;
252 *ncp++ = ((int)cp[i] + (int)cp[i-maxx]) >> 1;
253 }
254 }
255 } else {
256 memcpy(ncp, cp, maxx*4); /* Copy first line */
257 ncp += maxx*4;
258 for (y=1; y<maxy; y++) { /* Interpolate other lines */
259 for(x=0; x<maxx; x++) {
260 i = (y*maxx + x)*4 + 1;
261 *ncp++ = 0; /* Skip alfa comp */
262 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
263 i++;
264 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
265 i++;
266 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
267 }
268 }
269 }
270 return rv;
Jack Jansend26b4581993-01-22 15:34:43 +0000271}
272
Roger E. Massea141f8a1996-12-20 20:50:39 +0000273static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000274imageop_grey2mono(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000275{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000276 int tres, x, y, len;
277 unsigned char *cp, *ncp;
278 unsigned char ovalue;
279 PyObject *rv;
280 int i, bit;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000281
282
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000283 if ( !PyArg_ParseTuple(args, "s#iii", &cp, &len, &x, &y, &tres) )
284 return 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000285
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000286 if ( !check_multiply(len, x, y) )
287 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000288
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000289 rv = PyString_FromStringAndSize(NULL, (len+7)/8);
290 if ( rv == 0 )
291 return 0;
292 ncp = (unsigned char *)PyString_AsString(rv);
Roger E. Massea141f8a1996-12-20 20:50:39 +0000293
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000294 bit = 0x80;
295 ovalue = 0;
296 for ( i=0; i < len; i++ ) {
297 if ( (int)cp[i] > tres )
298 ovalue |= bit;
299 bit >>= 1;
300 if ( bit == 0 ) {
301 *ncp++ = ovalue;
302 bit = 0x80;
303 ovalue = 0;
304 }
305 }
306 if ( bit != 0x80 )
307 *ncp++ = ovalue;
308 return rv;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000309}
310
Roger E. Massea141f8a1996-12-20 20:50:39 +0000311static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000312imageop_grey2grey4(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000313{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000314 int x, y, len;
315 unsigned char *cp, *ncp;
316 unsigned char ovalue;
317 PyObject *rv;
318 int i;
319 int pos;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000320
321
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000322 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
323 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000324
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000325 if ( !check_multiply(len, x, y) )
326 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000327
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000328 rv = PyString_FromStringAndSize(NULL, (len+1)/2);
329 if ( rv == 0 )
330 return 0;
331 ncp = (unsigned char *)PyString_AsString(rv);
332 pos = 0;
333 ovalue = 0;
334 for ( i=0; i < len; i++ ) {
335 ovalue |= ((int)cp[i] & 0xf0) >> pos;
336 pos += 4;
337 if ( pos == 8 ) {
338 *ncp++ = ovalue;
339 ovalue = 0;
340 pos = 0;
341 }
342 }
343 if ( pos != 0 )
344 *ncp++ = ovalue;
345 return rv;
Jack Jansende3adf91992-12-22 14:05:55 +0000346}
347
Roger E. Massea141f8a1996-12-20 20:50:39 +0000348static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000349imageop_grey2grey2(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000350{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000351 int x, y, len;
352 unsigned char *cp, *ncp;
353 unsigned char ovalue;
354 PyObject *rv;
355 int i;
356 int pos;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000357
358
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000359 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
360 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000361
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000362 if ( !check_multiply(len, x, y) )
363 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000364
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000365 rv = PyString_FromStringAndSize(NULL, (len+3)/4);
366 if ( rv == 0 )
367 return 0;
368 ncp = (unsigned char *)PyString_AsString(rv);
369 pos = 0;
370 ovalue = 0;
371 for ( i=0; i < len; i++ ) {
372 ovalue |= ((int)cp[i] & 0xc0) >> pos;
373 pos += 2;
374 if ( pos == 8 ) {
375 *ncp++ = ovalue;
376 ovalue = 0;
377 pos = 0;
378 }
379 }
380 if ( pos != 0 )
381 *ncp++ = ovalue;
382 return rv;
Jack Jansende3adf91992-12-22 14:05:55 +0000383}
384
Roger E. Massea141f8a1996-12-20 20:50:39 +0000385static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000386imageop_dither2mono(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000387{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000388 int sum, x, y, len;
389 unsigned char *cp, *ncp;
390 unsigned char ovalue;
391 PyObject *rv;
392 int i, bit;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000393
394
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000395 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
396 return 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000397
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000398 if ( !check_multiply(len, x, y) )
399 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000400
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000401 rv = PyString_FromStringAndSize(NULL, (len+7)/8);
402 if ( rv == 0 )
403 return 0;
404 ncp = (unsigned char *)PyString_AsString(rv);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000405
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000406 bit = 0x80;
407 ovalue = 0;
408 sum = 0;
409 for ( i=0; i < len; i++ ) {
410 sum += cp[i];
411 if ( sum >= 256 ) {
412 sum -= 256;
413 ovalue |= bit;
414 }
415 bit >>= 1;
416 if ( bit == 0 ) {
417 *ncp++ = ovalue;
418 bit = 0x80;
419 ovalue = 0;
420 }
421 }
422 if ( bit != 0x80 )
423 *ncp++ = ovalue;
424 return rv;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000425}
426
Roger E. Massea141f8a1996-12-20 20:50:39 +0000427static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000428imageop_dither2grey2(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000429{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000430 int x, y, len;
431 unsigned char *cp, *ncp;
432 unsigned char ovalue;
433 PyObject *rv;
434 int i;
435 int pos;
436 int sum = 0, nvalue;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000437
438
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000439 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
440 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000441
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000442 if ( !check_multiply(len, x, y) )
443 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000444
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000445 rv = PyString_FromStringAndSize(NULL, (len+3)/4);
446 if ( rv == 0 )
447 return 0;
448 ncp = (unsigned char *)PyString_AsString(rv);
449 pos = 1;
450 ovalue = 0;
451 for ( i=0; i < len; i++ ) {
452 sum += cp[i];
453 nvalue = sum & 0x180;
454 sum -= nvalue;
455 ovalue |= nvalue >> pos;
456 pos += 2;
457 if ( pos == 9 ) {
458 *ncp++ = ovalue;
459 ovalue = 0;
460 pos = 1;
461 }
462 }
463 if ( pos != 0 )
464 *ncp++ = ovalue;
465 return rv;
Jack Jansende3adf91992-12-22 14:05:55 +0000466}
467
Roger E. Massea141f8a1996-12-20 20:50:39 +0000468static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000469imageop_mono2grey(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000470{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000471 int v0, v1, x, y, len, nlen;
472 unsigned char *cp, *ncp;
473 PyObject *rv;
474 int i, bit;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000475
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000476 if ( !PyArg_ParseTuple(args, "s#iiii", &cp, &len, &x, &y, &v0, &v1) )
477 return 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000478
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000479 nlen = x*y;
480 if ( !check_multiply(nlen, x, y) )
481 return 0;
482 if ( (nlen+7)/8 != len ) {
483 PyErr_SetString(ImageopError, "String has incorrect length");
484 return 0;
485 }
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000486
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000487 rv = PyString_FromStringAndSize(NULL, nlen);
488 if ( rv == 0 )
489 return 0;
490 ncp = (unsigned char *)PyString_AsString(rv);
Roger E. Massea141f8a1996-12-20 20:50:39 +0000491
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000492 bit = 0x80;
493 for ( i=0; i < nlen; i++ ) {
494 if ( *cp & bit )
495 *ncp++ = v1;
496 else
497 *ncp++ = v0;
498 bit >>= 1;
499 if ( bit == 0 ) {
500 bit = 0x80;
501 cp++;
502 }
503 }
504 return rv;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000505}
506
Roger E. Massea141f8a1996-12-20 20:50:39 +0000507static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000508imageop_grey22grey(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000509{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000510 int x, y, len, nlen;
511 unsigned char *cp, *ncp;
512 PyObject *rv;
513 int i, pos, value = 0, nvalue;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000514
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000515 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
516 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000517
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000518 nlen = x*y;
519 if ( !check_multiply(nlen, x, y) ) {
520 return 0;
521 }
522 if ( (nlen+3)/4 != len ) {
523 PyErr_SetString(ImageopError, "String has incorrect length");
524 return 0;
525 }
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000526
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000527 rv = PyString_FromStringAndSize(NULL, nlen);
528 if ( rv == 0 )
529 return 0;
530 ncp = (unsigned char *)PyString_AsString(rv);
Roger E. Massea141f8a1996-12-20 20:50:39 +0000531
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000532 pos = 0;
533 for ( i=0; i < nlen; i++ ) {
534 if ( pos == 0 ) {
535 value = *cp++;
536 pos = 8;
537 }
538 pos -= 2;
539 nvalue = (value >> pos) & 0x03;
540 *ncp++ = nvalue | (nvalue << 2) |
541 (nvalue << 4) | (nvalue << 6);
542 }
543 return rv;
Jack Jansende3adf91992-12-22 14:05:55 +0000544}
545
Roger E. Massea141f8a1996-12-20 20:50:39 +0000546static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000547imageop_grey42grey(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000548{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000549 int x, y, len, nlen;
550 unsigned char *cp, *ncp;
551 PyObject *rv;
552 int i, pos, value = 0, nvalue;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000553
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000554 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
555 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000556
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000557 nlen = x*y;
558 if ( !check_multiply(nlen, x, y) )
559 return 0;
560 if ( (nlen+1)/2 != len ) {
561 PyErr_SetString(ImageopError, "String has incorrect length");
562 return 0;
563 }
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000564
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000565 rv = PyString_FromStringAndSize(NULL, nlen);
566 if ( rv == 0 )
567 return 0;
568 ncp = (unsigned char *)PyString_AsString(rv);
Roger E. Massea141f8a1996-12-20 20:50:39 +0000569
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000570 pos = 0;
571 for ( i=0; i < nlen; i++ ) {
572 if ( pos == 0 ) {
573 value = *cp++;
574 pos = 8;
575 }
576 pos -= 4;
577 nvalue = (value >> pos) & 0x0f;
578 *ncp++ = nvalue | (nvalue << 4);
579 }
580 return rv;
Jack Jansende3adf91992-12-22 14:05:55 +0000581}
582
Roger E. Massea141f8a1996-12-20 20:50:39 +0000583static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000584imageop_rgb2rgb8(PyObject *self, PyObject *args)
Jack Jansen4fada9c1993-02-19 15:51:41 +0000585{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000586 int x, y, len, nlen;
587 unsigned char *cp;
588 unsigned char *ncp;
589 PyObject *rv;
590 int i, r, g, b;
591 int backward_compatible = imageop_backward_compatible();
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000592
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000593 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
594 return 0;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000595
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000596 if ( !check_multiply_size(len, x, "x", y, "y", 4) )
597 return 0;
598 nlen = x*y;
599 if ( !check_multiply(nlen, x, y) )
600 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000601
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000602 rv = PyString_FromStringAndSize(NULL, nlen);
603 if ( rv == 0 )
604 return 0;
605 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansen4fada9c1993-02-19 15:51:41 +0000606
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000607 for ( i=0; i < nlen; i++ ) {
608 /* Bits in source: aaaaaaaa BBbbbbbb GGGggggg RRRrrrrr */
609 if (backward_compatible) {
610 Py_UInt32 value = * (Py_UInt32 *) cp;
611 cp += 4;
612 r = (int) ((value & 0xff) / 255. * 7. + .5);
613 g = (int) (((value >> 8) & 0xff) / 255. * 7. + .5);
614 b = (int) (((value >> 16) & 0xff) / 255. * 3. + .5);
615 } else {
616 cp++; /* skip alpha channel */
617 b = (int) (*cp++ / 255. * 3. + .5);
618 g = (int) (*cp++ / 255. * 7. + .5);
619 r = (int) (*cp++ / 255. * 7. + .5);
620 }
621 *ncp++ = (unsigned char)((r<<5) | (b<<3) | g);
622 }
623 return rv;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000624}
625
Roger E. Massea141f8a1996-12-20 20:50:39 +0000626static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000627imageop_rgb82rgb(PyObject *self, PyObject *args)
Jack Jansen4fada9c1993-02-19 15:51:41 +0000628{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000629 int x, y, len, nlen;
630 unsigned char *cp;
631 unsigned char *ncp;
632 PyObject *rv;
633 int i, r, g, b;
634 unsigned char value;
635 int backward_compatible = imageop_backward_compatible();
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000636
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000637 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
638 return 0;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000639
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000640 if ( !check_multiply(len, x, y) )
641 return 0;
642 nlen = x*y*4;
643 if ( !check_multiply_size(nlen, x, "x", y, "y", 4) )
644 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000645
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000646 rv = PyString_FromStringAndSize(NULL, nlen);
647 if ( rv == 0 )
648 return 0;
649 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansen4fada9c1993-02-19 15:51:41 +0000650
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000651 for ( i=0; i < len; i++ ) {
652 /* Bits in source: RRRBBGGG
653 ** Red and Green are multiplied by 36.5, Blue by 85
654 */
655 value = *cp++;
656 r = (value >> 5) & 7;
657 g = (value ) & 7;
658 b = (value >> 3) & 3;
659 r = (r<<5) | (r<<3) | (r>>1);
660 g = (g<<5) | (g<<3) | (g>>1);
661 b = (b<<6) | (b<<4) | (b<<2) | b;
662 if (backward_compatible) {
663 Py_UInt32 nvalue = r | (g<<8) | (b<<16);
664 * (Py_UInt32 *) ncp = nvalue;
665 ncp += 4;
666 } else {
667 *ncp++ = 0;
668 *ncp++ = b;
669 *ncp++ = g;
670 *ncp++ = r;
671 }
672 }
673 return rv;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000674}
675
Roger E. Massea141f8a1996-12-20 20:50:39 +0000676static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000677imageop_rgb2grey(PyObject *self, PyObject *args)
Jack Jansen4fada9c1993-02-19 15:51:41 +0000678{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000679 int x, y, len, nlen;
680 unsigned char *cp;
681 unsigned char *ncp;
682 PyObject *rv;
683 int i, r, g, b;
684 int nvalue;
685 int backward_compatible = imageop_backward_compatible();
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000686
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000687 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
688 return 0;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000689
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000690 if ( !check_multiply_size(len, x, "x", y, "y", 4) )
691 return 0;
692 nlen = x*y;
693 if ( !check_multiply(nlen, x, y) )
694 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000695
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000696 rv = PyString_FromStringAndSize(NULL, nlen);
697 if ( rv == 0 )
698 return 0;
699 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansen4fada9c1993-02-19 15:51:41 +0000700
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000701 for ( i=0; i < nlen; i++ ) {
702 if (backward_compatible) {
703 Py_UInt32 value = * (Py_UInt32 *) cp;
704 cp += 4;
705 r = (int) ((value & 0xff) / 255. * 7. + .5);
706 g = (int) (((value >> 8) & 0xff) / 255. * 7. + .5);
707 b = (int) (((value >> 16) & 0xff) / 255. * 3. + .5);
708 } else {
709 cp++; /* skip alpha channel */
710 b = *cp++;
711 g = *cp++;
712 r = *cp++;
713 }
714 nvalue = (int)(0.30*r + 0.59*g + 0.11*b);
715 if ( nvalue > 255 ) nvalue = 255;
716 *ncp++ = (unsigned char)nvalue;
717 }
718 return rv;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000719}
720
Roger E. Massea141f8a1996-12-20 20:50:39 +0000721static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000722imageop_grey2rgb(PyObject *self, PyObject *args)
Jack Jansen4fada9c1993-02-19 15:51:41 +0000723{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000724 int x, y, len, nlen;
725 unsigned char *cp;
726 unsigned char *ncp;
727 PyObject *rv;
728 int i;
729 unsigned char value;
730 int backward_compatible = imageop_backward_compatible();
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000731
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000732 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
733 return 0;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000734
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000735 if ( !check_multiply(len, x, y) )
736 return 0;
737 nlen = x*y*4;
738 if ( !check_multiply_size(nlen, x, "x", y, "y", 4) )
739 return 0;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000740
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000741 rv = PyString_FromStringAndSize(NULL, nlen);
742 if ( rv == 0 )
743 return 0;
744 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansen4fada9c1993-02-19 15:51:41 +0000745
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000746 for ( i=0; i < len; i++ ) {
747 value = *cp++;
748 if (backward_compatible) {
749 * (Py_UInt32 *) ncp = (Py_UInt32) value | ((Py_UInt32) value << 8 ) | ((Py_UInt32) value << 16);
750 ncp += 4;
751 } else {
752 *ncp++ = 0;
753 *ncp++ = value;
754 *ncp++ = value;
755 *ncp++ = value;
756 }
757 }
758 return rv;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000759}
760
Roger E. Massea141f8a1996-12-20 20:50:39 +0000761static PyMethodDef imageop_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000762 { "crop", imageop_crop, METH_VARARGS },
763 { "scale", imageop_scale, METH_VARARGS },
764 { "grey2mono", imageop_grey2mono, METH_VARARGS },
765 { "grey2grey2", imageop_grey2grey2, METH_VARARGS },
766 { "grey2grey4", imageop_grey2grey4, METH_VARARGS },
767 { "dither2mono", imageop_dither2mono, METH_VARARGS },
768 { "dither2grey2", imageop_dither2grey2, METH_VARARGS },
769 { "mono2grey", imageop_mono2grey, METH_VARARGS },
770 { "grey22grey", imageop_grey22grey, METH_VARARGS },
771 { "grey42grey", imageop_grey42grey, METH_VARARGS },
772 { "tovideo", imageop_tovideo, METH_VARARGS },
773 { "rgb2rgb8", imageop_rgb2rgb8, METH_VARARGS },
774 { "rgb82rgb", imageop_rgb82rgb, METH_VARARGS },
775 { "rgb2grey", imageop_rgb2grey, METH_VARARGS },
776 { "grey2rgb", imageop_grey2rgb, METH_VARARGS },
777 { 0, 0 }
Guido van Rossum0317a471992-10-26 13:40:15 +0000778};
779
780
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000781PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000782initimageop(void)
Guido van Rossum0317a471992-10-26 13:40:15 +0000783{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000784 PyObject *m;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000785
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000786 if (PyErr_WarnPy3k("the imageop module has been removed in "
787 "Python 3.0", 2) < 0)
788 return;
Benjamin Peterson8d77d442008-09-30 01:31:49 +0000789
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000790 m = Py_InitModule("imageop", imageop_methods);
791 if (m == NULL)
792 return;
793 ImageopDict = PyModule_GetDict(m);
794 ImageopError = PyErr_NewException("imageop.error", NULL, NULL);
795 if (ImageopError != NULL)
796 PyDict_SetItemString(ImageopDict, "error", ImageopError);
Guido van Rossum0317a471992-10-26 13:40:15 +0000797}