blob: 5b87898bbbfd686e29fdf1e763f5769e84105e2e [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
29/* If this function returns true (the default if anything goes wrong), we're
30 behaving in a backward-compatible way with respect to how multi-byte pixels
31 are stored in the strings. The code in this module was originally written
32 for an SGI which is a big-endian system, and so the old code assumed that
33 4-byte integers hold the R, G, and B values in a particular order.
34 However, on little-endian systems the order is reversed, and so not
35 actually compatible with what gl.lrectwrite and imgfile expect.
36 (gl.lrectwrite and imgfile are also SGI-specific, however, it is
37 conceivable that the data handled here comes from or goes to an SGI or that
38 it is otherwise used in the expectation that the byte order in the strings
39 is as specified.)
40
41 The function returns the value of the module variable
42 "backward_compatible", or 1 if the variable does not exist or is not an
43 int.
44 */
45
46static int
47imageop_backward_compatible(void)
48{
49 static PyObject *bcos;
50 PyObject *bco;
51 long rc;
52
53 if (ImageopDict == NULL) /* "cannot happen" */
54 return 1;
55 if (bcos == NULL) {
56 /* cache string object for future use */
57 bcos = PyString_FromString("backward_compatible");
58 if (bcos == NULL)
59 return 1;
60 }
61 bco = PyDict_GetItem(ImageopDict, bcos);
62 if (bco == NULL)
63 return 1;
64 if (!PyInt_Check(bco))
65 return 1;
66 rc = PyInt_AsLong(bco);
67 if (PyErr_Occurred()) {
68 /* not an integer, or too large, or something */
69 PyErr_Clear();
70 rc = 1;
71 }
72 return rc != 0; /* convert to values 0, 1 */
73}
74
Roger E. Massea141f8a1996-12-20 20:50:39 +000075static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +000076imageop_crop(PyObject *self, PyObject *args)
Guido van Rossum0317a471992-10-26 13:40:15 +000077{
Roger E. Massea141f8a1996-12-20 20:50:39 +000078 char *cp, *ncp;
79 short *nsp;
Guido van Rossum69011961998-04-23 20:23:00 +000080 Py_Int32 *nlp;
Roger E. Massea141f8a1996-12-20 20:50:39 +000081 int len, size, x, y, newx1, newx2, newy1, newy2;
82 int ix, iy, xstep, ystep;
83 PyObject *rv;
Guido van Rossum0317a471992-10-26 13:40:15 +000084
Neal Norwitzb0aaec52002-04-02 18:26:33 +000085 if ( !PyArg_ParseTuple(args, "s#iiiiiii", &cp, &len, &size, &x, &y,
Roger E. Massea141f8a1996-12-20 20:50:39 +000086 &newx1, &newy1, &newx2, &newy2) )
87 return 0;
Guido van Rossum0317a471992-10-26 13:40:15 +000088
Roger E. Massea141f8a1996-12-20 20:50:39 +000089 if ( size != 1 && size != 2 && size != 4 ) {
90 PyErr_SetString(ImageopError, "Size should be 1, 2 or 4");
91 return 0;
Guido van Rossum0317a471992-10-26 13:40:15 +000092 }
Roger E. Massea141f8a1996-12-20 20:50:39 +000093 if ( len != size*x*y ) {
94 PyErr_SetString(ImageopError, "String has incorrect length");
95 return 0;
96 }
97 xstep = (newx1 < newx2)? 1 : -1;
98 ystep = (newy1 < newy2)? 1 : -1;
99
100 rv = PyString_FromStringAndSize(NULL,
101 (abs(newx2-newx1)+1)*(abs(newy2-newy1)+1)*size);
102 if ( rv == 0 )
103 return 0;
104 ncp = (char *)PyString_AsString(rv);
105 nsp = (short *)ncp;
Guido van Rossum69011961998-04-23 20:23:00 +0000106 nlp = (Py_Int32 *)ncp;
Roger E. Massea141f8a1996-12-20 20:50:39 +0000107 newy2 += ystep;
108 newx2 += xstep;
109 for( iy = newy1; iy != newy2; iy+=ystep ) {
110 for ( ix = newx1; ix != newx2; ix+=xstep ) {
111 if ( iy < 0 || iy >= y || ix < 0 || ix >= x ) {
112 if ( size == 1 )
113 *ncp++ = 0;
114 else
115 *nlp++ = 0;
116 } else {
117 if ( size == 1 )
118 *ncp++ = *CHARP(cp, x, ix, iy);
119 else if ( size == 2 )
120 *nsp++ = *SHORTP(cp, x, ix, iy);
121 else
122 *nlp++ = *LONGP(cp, x, ix, iy);
123 }
124 }
125 }
126 return rv;
Guido van Rossum0317a471992-10-26 13:40:15 +0000127}
128
Roger E. Massea141f8a1996-12-20 20:50:39 +0000129static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000130imageop_scale(PyObject *self, PyObject *args)
Guido van Rossum0317a471992-10-26 13:40:15 +0000131{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000132 char *cp, *ncp;
133 short *nsp;
Guido van Rossum69011961998-04-23 20:23:00 +0000134 Py_Int32 *nlp;
Roger E. Massea141f8a1996-12-20 20:50:39 +0000135 int len, size, x, y, newx, newy;
136 int ix, iy;
137 int oix, oiy;
138 PyObject *rv;
Guido van Rossum0317a471992-10-26 13:40:15 +0000139
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000140 if ( !PyArg_ParseTuple(args, "s#iiiii",
Roger E. Massea141f8a1996-12-20 20:50:39 +0000141 &cp, &len, &size, &x, &y, &newx, &newy) )
142 return 0;
Guido van Rossum0317a471992-10-26 13:40:15 +0000143
Roger E. Massea141f8a1996-12-20 20:50:39 +0000144 if ( size != 1 && size != 2 && size != 4 ) {
145 PyErr_SetString(ImageopError, "Size should be 1, 2 or 4");
146 return 0;
Guido van Rossum0317a471992-10-26 13:40:15 +0000147 }
Roger E. Massea141f8a1996-12-20 20:50:39 +0000148 if ( len != size*x*y ) {
149 PyErr_SetString(ImageopError, "String has incorrect length");
150 return 0;
151 }
152
153 rv = PyString_FromStringAndSize(NULL, newx*newy*size);
154 if ( rv == 0 )
155 return 0;
156 ncp = (char *)PyString_AsString(rv);
157 nsp = (short *)ncp;
Guido van Rossum69011961998-04-23 20:23:00 +0000158 nlp = (Py_Int32 *)ncp;
Roger E. Massea141f8a1996-12-20 20:50:39 +0000159 for( iy = 0; iy < newy; iy++ ) {
160 for ( ix = 0; ix < newx; ix++ ) {
161 oix = ix * x / newx;
162 oiy = iy * y / newy;
163 if ( size == 1 )
164 *ncp++ = *CHARP(cp, x, oix, oiy);
165 else if ( size == 2 )
166 *nsp++ = *SHORTP(cp, x, oix, oiy);
167 else
168 *nlp++ = *LONGP(cp, x, oix, oiy);
169 }
170 }
171 return rv;
Guido van Rossum0317a471992-10-26 13:40:15 +0000172}
173
Jack Jansend26b4581993-01-22 15:34:43 +0000174/* Note: this routine can use a bit of optimizing */
175
Roger E. Massea141f8a1996-12-20 20:50:39 +0000176static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000177imageop_tovideo(PyObject *self, PyObject *args)
Jack Jansend26b4581993-01-22 15:34:43 +0000178{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000179 int maxx, maxy, x, y, len;
180 int i;
181 unsigned char *cp, *ncp;
182 int width;
183 PyObject *rv;
Jack Jansend26b4581993-01-22 15:34:43 +0000184
185
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000186 if ( !PyArg_ParseTuple(args, "s#iii", &cp, &len, &width, &maxx, &maxy) )
Roger E. Massea141f8a1996-12-20 20:50:39 +0000187 return 0;
Jack Jansend26b4581993-01-22 15:34:43 +0000188
Roger E. Massea141f8a1996-12-20 20:50:39 +0000189 if ( width != 1 && width != 4 ) {
190 PyErr_SetString(ImageopError, "Size should be 1 or 4");
191 return 0;
192 }
193 if ( maxx*maxy*width != len ) {
194 PyErr_SetString(ImageopError, "String has incorrect length");
195 return 0;
196 }
Jack Jansend26b4581993-01-22 15:34:43 +0000197
Roger E. Massea141f8a1996-12-20 20:50:39 +0000198 rv = PyString_FromStringAndSize(NULL, len);
199 if ( rv == 0 )
200 return 0;
201 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansend26b4581993-01-22 15:34:43 +0000202
Roger E. Massea141f8a1996-12-20 20:50:39 +0000203 if ( width == 1 ) {
204 memcpy(ncp, cp, maxx); /* Copy first line */
205 ncp += maxx;
206 for (y=1; y<maxy; y++) { /* Interpolate other lines */
207 for(x=0; x<maxx; x++) {
208 i = y*maxx + x;
209 *ncp++ = ((int)cp[i] + (int)cp[i-maxx]) >> 1;
210 }
211 }
212 } else {
213 memcpy(ncp, cp, maxx*4); /* Copy first line */
214 ncp += maxx*4;
215 for (y=1; y<maxy; y++) { /* Interpolate other lines */
216 for(x=0; x<maxx; x++) {
217 i = (y*maxx + x)*4 + 1;
218 *ncp++ = 0; /* Skip alfa comp */
219 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
220 i++;
221 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
222 i++;
223 *ncp++ = ((int)cp[i] + (int)cp[i-4*maxx]) >> 1;
224 }
225 }
Jack Jansend26b4581993-01-22 15:34:43 +0000226 }
Roger E. Massea141f8a1996-12-20 20:50:39 +0000227 return rv;
Jack Jansend26b4581993-01-22 15:34:43 +0000228}
229
Roger E. Massea141f8a1996-12-20 20:50:39 +0000230static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000231imageop_grey2mono(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000232{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000233 int tres, x, y, len;
234 unsigned char *cp, *ncp;
235 unsigned char ovalue;
236 PyObject *rv;
237 int i, bit;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000238
239
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000240 if ( !PyArg_ParseTuple(args, "s#iii", &cp, &len, &x, &y, &tres) )
Roger E. Massea141f8a1996-12-20 20:50:39 +0000241 return 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000242
Roger E. Massea141f8a1996-12-20 20:50:39 +0000243 if ( x*y != len ) {
244 PyErr_SetString(ImageopError, "String has incorrect length");
245 return 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000246 }
Roger E. Massea141f8a1996-12-20 20:50:39 +0000247
248 rv = PyString_FromStringAndSize(NULL, (len+7)/8);
249 if ( rv == 0 )
250 return 0;
251 ncp = (unsigned char *)PyString_AsString(rv);
252
253 bit = 0x80;
254 ovalue = 0;
255 for ( i=0; i < len; i++ ) {
256 if ( (int)cp[i] > tres )
257 ovalue |= bit;
258 bit >>= 1;
259 if ( bit == 0 ) {
260 *ncp++ = ovalue;
261 bit = 0x80;
262 ovalue = 0;
263 }
264 }
265 if ( bit != 0x80 )
266 *ncp++ = ovalue;
267 return rv;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000268}
269
Roger E. Massea141f8a1996-12-20 20:50:39 +0000270static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000271imageop_grey2grey4(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000272{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000273 int x, y, len;
274 unsigned char *cp, *ncp;
275 unsigned char ovalue;
276 PyObject *rv;
277 int i;
278 int pos;
Jack Jansende3adf91992-12-22 14:05:55 +0000279
280
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000281 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
Roger E. Massea141f8a1996-12-20 20:50:39 +0000282 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000283
Roger E. Massea141f8a1996-12-20 20:50:39 +0000284 if ( x*y != len ) {
285 PyErr_SetString(ImageopError, "String has incorrect length");
286 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000287 }
Roger E. Massea141f8a1996-12-20 20:50:39 +0000288
289 rv = PyString_FromStringAndSize(NULL, (len+1)/2);
290 if ( rv == 0 )
291 return 0;
292 ncp = (unsigned char *)PyString_AsString(rv);
293 pos = 0;
294 ovalue = 0;
295 for ( i=0; i < len; i++ ) {
296 ovalue |= ((int)cp[i] & 0xf0) >> pos;
297 pos += 4;
298 if ( pos == 8 ) {
299 *ncp++ = ovalue;
300 ovalue = 0;
301 pos = 0;
302 }
303 }
304 if ( pos != 0 )
305 *ncp++ = ovalue;
306 return rv;
Jack Jansende3adf91992-12-22 14:05:55 +0000307}
308
Roger E. Massea141f8a1996-12-20 20:50:39 +0000309static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000310imageop_grey2grey2(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000311{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000312 int x, y, len;
313 unsigned char *cp, *ncp;
314 unsigned char ovalue;
315 PyObject *rv;
316 int i;
317 int pos;
Jack Jansende3adf91992-12-22 14:05:55 +0000318
319
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000320 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
Roger E. Massea141f8a1996-12-20 20:50:39 +0000321 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000322
Roger E. Massea141f8a1996-12-20 20:50:39 +0000323 if ( x*y != len ) {
324 PyErr_SetString(ImageopError, "String has incorrect length");
325 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000326 }
Roger E. Massea141f8a1996-12-20 20:50:39 +0000327
328 rv = PyString_FromStringAndSize(NULL, (len+3)/4);
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] & 0xc0) >> pos;
336 pos += 2;
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_dither2mono(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000350{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000351 int sum, x, y, len;
352 unsigned char *cp, *ncp;
353 unsigned char ovalue;
354 PyObject *rv;
355 int i, bit;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000356
357
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000358 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
Roger E. Massea141f8a1996-12-20 20:50:39 +0000359 return 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000360
Roger E. Massea141f8a1996-12-20 20:50:39 +0000361 if ( x*y != len ) {
362 PyErr_SetString(ImageopError, "String has incorrect length");
363 return 0;
364 }
Guido van Rossum5f59d601992-12-14 16:59:51 +0000365
Roger E. Massea141f8a1996-12-20 20:50:39 +0000366 rv = PyString_FromStringAndSize(NULL, (len+7)/8);
367 if ( rv == 0 )
368 return 0;
369 ncp = (unsigned char *)PyString_AsString(rv);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000370
Roger E. Massea141f8a1996-12-20 20:50:39 +0000371 bit = 0x80;
372 ovalue = 0;
373 sum = 0;
374 for ( i=0; i < len; i++ ) {
375 sum += cp[i];
376 if ( sum >= 256 ) {
377 sum -= 256;
378 ovalue |= bit;
379 }
380 bit >>= 1;
381 if ( bit == 0 ) {
382 *ncp++ = ovalue;
383 bit = 0x80;
384 ovalue = 0;
385 }
Guido van Rossum5f59d601992-12-14 16:59:51 +0000386 }
Roger E. Massea141f8a1996-12-20 20:50:39 +0000387 if ( bit != 0x80 )
388 *ncp++ = ovalue;
389 return rv;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000390}
391
Roger E. Massea141f8a1996-12-20 20:50:39 +0000392static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000393imageop_dither2grey2(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000394{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000395 int x, y, len;
396 unsigned char *cp, *ncp;
397 unsigned char ovalue;
398 PyObject *rv;
399 int i;
400 int pos;
401 int sum = 0, nvalue;
Jack Jansende3adf91992-12-22 14:05:55 +0000402
403
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000404 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
Roger E. Massea141f8a1996-12-20 20:50:39 +0000405 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000406
Roger E. Massea141f8a1996-12-20 20:50:39 +0000407 if ( x*y != len ) {
408 PyErr_SetString(ImageopError, "String has incorrect length");
409 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000410 }
Roger E. Massea141f8a1996-12-20 20:50:39 +0000411
412 rv = PyString_FromStringAndSize(NULL, (len+3)/4);
413 if ( rv == 0 )
414 return 0;
415 ncp = (unsigned char *)PyString_AsString(rv);
416 pos = 1;
417 ovalue = 0;
418 for ( i=0; i < len; i++ ) {
419 sum += cp[i];
420 nvalue = sum & 0x180;
421 sum -= nvalue;
422 ovalue |= nvalue >> pos;
423 pos += 2;
424 if ( pos == 9 ) {
425 *ncp++ = ovalue;
426 ovalue = 0;
427 pos = 1;
428 }
429 }
430 if ( pos != 0 )
431 *ncp++ = ovalue;
432 return rv;
Jack Jansende3adf91992-12-22 14:05:55 +0000433}
434
Roger E. Massea141f8a1996-12-20 20:50:39 +0000435static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000436imageop_mono2grey(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000437{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000438 int v0, v1, x, y, len, nlen;
439 unsigned char *cp, *ncp;
440 PyObject *rv;
441 int i, bit;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000442
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000443 if ( !PyArg_ParseTuple(args, "s#iiii", &cp, &len, &x, &y, &v0, &v1) )
Roger E. Massea141f8a1996-12-20 20:50:39 +0000444 return 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000445
Roger E. Massea141f8a1996-12-20 20:50:39 +0000446 nlen = x*y;
447 if ( (nlen+7)/8 != len ) {
448 PyErr_SetString(ImageopError, "String has incorrect length");
449 return 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000450 }
Roger E. Massea141f8a1996-12-20 20:50:39 +0000451
452 rv = PyString_FromStringAndSize(NULL, nlen);
453 if ( rv == 0 )
454 return 0;
455 ncp = (unsigned char *)PyString_AsString(rv);
456
457 bit = 0x80;
458 for ( i=0; i < nlen; i++ ) {
459 if ( *cp & bit )
460 *ncp++ = v1;
461 else
462 *ncp++ = v0;
463 bit >>= 1;
464 if ( bit == 0 ) {
465 bit = 0x80;
466 cp++;
467 }
468 }
469 return rv;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000470}
471
Roger E. Massea141f8a1996-12-20 20:50:39 +0000472static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000473imageop_grey22grey(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000474{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000475 int x, y, len, nlen;
476 unsigned char *cp, *ncp;
477 PyObject *rv;
478 int i, pos, value = 0, nvalue;
Jack Jansende3adf91992-12-22 14:05:55 +0000479
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000480 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
Roger E. Massea141f8a1996-12-20 20:50:39 +0000481 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000482
Roger E. Massea141f8a1996-12-20 20:50:39 +0000483 nlen = x*y;
484 if ( (nlen+3)/4 != len ) {
485 PyErr_SetString(ImageopError, "String has incorrect length");
486 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000487 }
Roger E. Massea141f8a1996-12-20 20:50:39 +0000488
489 rv = PyString_FromStringAndSize(NULL, nlen);
490 if ( rv == 0 )
491 return 0;
492 ncp = (unsigned char *)PyString_AsString(rv);
493
494 pos = 0;
495 for ( i=0; i < nlen; i++ ) {
496 if ( pos == 0 ) {
497 value = *cp++;
498 pos = 8;
499 }
500 pos -= 2;
501 nvalue = (value >> pos) & 0x03;
502 *ncp++ = nvalue | (nvalue << 2) |
503 (nvalue << 4) | (nvalue << 6);
504 }
505 return rv;
Jack Jansende3adf91992-12-22 14:05:55 +0000506}
507
Roger E. Massea141f8a1996-12-20 20:50:39 +0000508static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000509imageop_grey42grey(PyObject *self, PyObject *args)
Jack Jansende3adf91992-12-22 14:05:55 +0000510{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000511 int x, y, len, nlen;
512 unsigned char *cp, *ncp;
513 PyObject *rv;
514 int i, pos, value = 0, nvalue;
Jack Jansende3adf91992-12-22 14:05:55 +0000515
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000516 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
Roger E. Massea141f8a1996-12-20 20:50:39 +0000517 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000518
Roger E. Massea141f8a1996-12-20 20:50:39 +0000519 nlen = x*y;
520 if ( (nlen+1)/2 != len ) {
521 PyErr_SetString(ImageopError, "String has incorrect length");
522 return 0;
Jack Jansende3adf91992-12-22 14:05:55 +0000523 }
Roger E. Massea141f8a1996-12-20 20:50:39 +0000524
525 rv = PyString_FromStringAndSize(NULL, nlen);
526 if ( rv == 0 )
527 return 0;
528 ncp = (unsigned char *)PyString_AsString(rv);
529
530 pos = 0;
531 for ( i=0; i < nlen; i++ ) {
532 if ( pos == 0 ) {
533 value = *cp++;
534 pos = 8;
535 }
536 pos -= 4;
537 nvalue = (value >> pos) & 0x0f;
538 *ncp++ = nvalue | (nvalue << 4);
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_rgb2rgb8(PyObject *self, PyObject *args)
Jack Jansen4fada9c1993-02-19 15:51:41 +0000545{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000546 int x, y, len, nlen;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000547 unsigned char *cp;
Roger E. Massea141f8a1996-12-20 20:50:39 +0000548 unsigned char *ncp;
549 PyObject *rv;
550 int i, r, g, b;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000551 int backward_compatible = imageop_backward_compatible();
Jack Jansen4fada9c1993-02-19 15:51:41 +0000552
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000553 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
Roger E. Massea141f8a1996-12-20 20:50:39 +0000554 return 0;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000555
Roger E. Massea141f8a1996-12-20 20:50:39 +0000556 nlen = x*y;
557 if ( nlen*4 != len ) {
558 PyErr_SetString(ImageopError, "String has incorrect length");
559 return 0;
560 }
Jack Jansen4fada9c1993-02-19 15:51:41 +0000561
Roger E. Massea141f8a1996-12-20 20:50:39 +0000562 rv = PyString_FromStringAndSize(NULL, nlen);
563 if ( rv == 0 )
564 return 0;
565 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansen4fada9c1993-02-19 15:51:41 +0000566
Roger E. Massea141f8a1996-12-20 20:50:39 +0000567 for ( i=0; i < nlen; i++ ) {
568 /* Bits in source: aaaaaaaa BBbbbbbb GGGggggg RRRrrrrr */
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000569 if (backward_compatible) {
570 Py_UInt32 value = * (Py_UInt32 *) cp;
571 cp += 4;
572 r = (int) ((value & 0xff) / 255. * 7. + .5);
573 g = (int) (((value >> 8) & 0xff) / 255. * 7. + .5);
574 b = (int) (((value >> 16) & 0xff) / 255. * 3. + .5);
575 } else {
576 cp++; /* skip alpha channel */
577 b = (int) (*cp++ / 255. * 3. + .5);
578 g = (int) (*cp++ / 255. * 7. + .5);
579 r = (int) (*cp++ / 255. * 7. + .5);
580 }
581 *ncp++ = (unsigned char)((r<<5) | (b<<3) | g);
Roger E. Massea141f8a1996-12-20 20:50:39 +0000582 }
583 return rv;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000584}
585
Roger E. Massea141f8a1996-12-20 20:50:39 +0000586static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000587imageop_rgb82rgb(PyObject *self, PyObject *args)
Jack Jansen4fada9c1993-02-19 15:51:41 +0000588{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000589 int x, y, len, nlen;
590 unsigned char *cp;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000591 unsigned char *ncp;
Roger E. Massea141f8a1996-12-20 20:50:39 +0000592 PyObject *rv;
593 int i, r, g, b;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000594 unsigned char value;
595 int backward_compatible = imageop_backward_compatible();
Jack Jansen4fada9c1993-02-19 15:51:41 +0000596
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000597 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
Roger E. Massea141f8a1996-12-20 20:50:39 +0000598 return 0;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000599
Roger E. Massea141f8a1996-12-20 20:50:39 +0000600 nlen = x*y;
601 if ( nlen != len ) {
602 PyErr_SetString(ImageopError, "String has incorrect length");
603 return 0;
604 }
Jack Jansen4fada9c1993-02-19 15:51:41 +0000605
Roger E. Massea141f8a1996-12-20 20:50:39 +0000606 rv = PyString_FromStringAndSize(NULL, nlen*4);
607 if ( rv == 0 )
608 return 0;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000609 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansen4fada9c1993-02-19 15:51:41 +0000610
Roger E. Massea141f8a1996-12-20 20:50:39 +0000611 for ( i=0; i < nlen; i++ ) {
612 /* Bits in source: RRRBBGGG
613 ** Red and Green are multiplied by 36.5, Blue by 85
614 */
615 value = *cp++;
616 r = (value >> 5) & 7;
617 g = (value ) & 7;
618 b = (value >> 3) & 3;
619 r = (r<<5) | (r<<3) | (r>>1);
620 g = (g<<5) | (g<<3) | (g>>1);
621 b = (b<<6) | (b<<4) | (b<<2) | b;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000622 if (backward_compatible) {
623 Py_UInt32 nvalue = r | (g<<8) | (b<<16);
624 * (Py_UInt32 *) ncp = nvalue;
625 ncp += 4;
626 } else {
627 *ncp++ = 0;
628 *ncp++ = b;
629 *ncp++ = g;
630 *ncp++ = r;
631 }
Roger E. Massea141f8a1996-12-20 20:50:39 +0000632 }
633 return rv;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000634}
635
Roger E. Massea141f8a1996-12-20 20:50:39 +0000636static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000637imageop_rgb2grey(PyObject *self, PyObject *args)
Jack Jansen4fada9c1993-02-19 15:51:41 +0000638{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000639 int x, y, len, nlen;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000640 unsigned char *cp;
Roger E. Massea141f8a1996-12-20 20:50:39 +0000641 unsigned char *ncp;
642 PyObject *rv;
643 int i, r, g, b;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000644 int nvalue;
645 int backward_compatible = imageop_backward_compatible();
Jack Jansen4fada9c1993-02-19 15:51:41 +0000646
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000647 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
Roger E. Massea141f8a1996-12-20 20:50:39 +0000648 return 0;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000649
Roger E. Massea141f8a1996-12-20 20:50:39 +0000650 nlen = x*y;
651 if ( nlen*4 != len ) {
652 PyErr_SetString(ImageopError, "String has incorrect length");
653 return 0;
654 }
Jack Jansen4fada9c1993-02-19 15:51:41 +0000655
Roger E. Massea141f8a1996-12-20 20:50:39 +0000656 rv = PyString_FromStringAndSize(NULL, nlen);
657 if ( rv == 0 )
658 return 0;
659 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansen4fada9c1993-02-19 15:51:41 +0000660
Roger E. Massea141f8a1996-12-20 20:50:39 +0000661 for ( i=0; i < nlen; i++ ) {
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000662 if (backward_compatible) {
663 Py_UInt32 value = * (Py_UInt32 *) cp;
664 cp += 4;
665 r = (int) ((value & 0xff) / 255. * 7. + .5);
666 g = (int) (((value >> 8) & 0xff) / 255. * 7. + .5);
667 b = (int) (((value >> 16) & 0xff) / 255. * 3. + .5);
668 } else {
669 cp++; /* skip alpha channel */
670 b = *cp++;
671 g = *cp++;
672 r = *cp++;
673 }
Roger E. Massea141f8a1996-12-20 20:50:39 +0000674 nvalue = (int)(0.30*r + 0.59*g + 0.11*b);
675 if ( nvalue > 255 ) nvalue = 255;
Guido van Rossum644a12b1997-04-09 19:24:53 +0000676 *ncp++ = (unsigned char)nvalue;
Roger E. Massea141f8a1996-12-20 20:50:39 +0000677 }
678 return rv;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000679}
680
Roger E. Massea141f8a1996-12-20 20:50:39 +0000681static PyObject *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000682imageop_grey2rgb(PyObject *self, PyObject *args)
Jack Jansen4fada9c1993-02-19 15:51:41 +0000683{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000684 int x, y, len, nlen;
685 unsigned char *cp;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000686 unsigned char *ncp;
Roger E. Massea141f8a1996-12-20 20:50:39 +0000687 PyObject *rv;
688 int i;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000689 unsigned char value;
690 int backward_compatible = imageop_backward_compatible();
Jack Jansen4fada9c1993-02-19 15:51:41 +0000691
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000692 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) )
Roger E. Massea141f8a1996-12-20 20:50:39 +0000693 return 0;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000694
Roger E. Massea141f8a1996-12-20 20:50:39 +0000695 nlen = x*y;
696 if ( nlen != len ) {
697 PyErr_SetString(ImageopError, "String has incorrect length");
698 return 0;
699 }
Jack Jansen4fada9c1993-02-19 15:51:41 +0000700
Roger E. Massea141f8a1996-12-20 20:50:39 +0000701 rv = PyString_FromStringAndSize(NULL, nlen*4);
702 if ( rv == 0 )
703 return 0;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000704 ncp = (unsigned char *)PyString_AsString(rv);
Jack Jansen4fada9c1993-02-19 15:51:41 +0000705
Roger E. Massea141f8a1996-12-20 20:50:39 +0000706 for ( i=0; i < nlen; i++ ) {
707 value = *cp++;
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000708 if (backward_compatible) {
709 * (Py_UInt32 *) ncp = (Py_UInt32) value | ((Py_UInt32) value << 8 ) | ((Py_UInt32) value << 16);
710 ncp += 4;
711 } else {
712 *ncp++ = 0;
713 *ncp++ = value;
714 *ncp++ = value;
715 *ncp++ = value;
716 }
Roger E. Massea141f8a1996-12-20 20:50:39 +0000717 }
718 return rv;
Jack Jansen4fada9c1993-02-19 15:51:41 +0000719}
720
Guido van Rossum0317a471992-10-26 13:40:15 +0000721/*
722static object *
Peter Schneider-Kampfe742632000-07-10 09:55:32 +0000723imageop_mul(object *self, object *args)
Guido van Rossum0317a471992-10-26 13:40:15 +0000724{
Roger E. Massea141f8a1996-12-20 20:50:39 +0000725 char *cp, *ncp;
726 int len, size, x, y;
727 object *rv;
728 int i;
Guido van Rossum0317a471992-10-26 13:40:15 +0000729
Roger E. Massea141f8a1996-12-20 20:50:39 +0000730 if ( !getargs(args, "(s#iii)", &cp, &len, &size, &x, &y) )
731 return 0;
Guido van Rossum0317a471992-10-26 13:40:15 +0000732
Roger E. Massea141f8a1996-12-20 20:50:39 +0000733 if ( size != 1 && size != 4 ) {
734 err_setstr(ImageopError, "Size should be 1 or 4");
735 return 0;
736 }
737 if ( len != size*x*y ) {
738 err_setstr(ImageopError, "String has incorrect length");
739 return 0;
740 }
Guido van Rossum0317a471992-10-26 13:40:15 +0000741
Roger E. Massea141f8a1996-12-20 20:50:39 +0000742 rv = newsizedstringobject(NULL, XXXX);
743 if ( rv == 0 )
744 return 0;
745 ncp = (char *)getstringvalue(rv);
Guido van Rossum0317a471992-10-26 13:40:15 +0000746
747
Roger E. Massea141f8a1996-12-20 20:50:39 +0000748 for ( i=0; i < len; i += size ) {
749 }
750 return rv;
Guido van Rossum0317a471992-10-26 13:40:15 +0000751}
752*/
753
Roger E. Massea141f8a1996-12-20 20:50:39 +0000754static PyMethodDef imageop_methods[] = {
Neal Norwitzb0aaec52002-04-02 18:26:33 +0000755 { "crop", imageop_crop, METH_VARARGS },
756 { "scale", imageop_scale, METH_VARARGS },
757 { "grey2mono", imageop_grey2mono, METH_VARARGS },
758 { "grey2grey2", imageop_grey2grey2, METH_VARARGS },
759 { "grey2grey4", imageop_grey2grey4, METH_VARARGS },
760 { "dither2mono", imageop_dither2mono, METH_VARARGS },
761 { "dither2grey2", imageop_dither2grey2, METH_VARARGS },
762 { "mono2grey", imageop_mono2grey, METH_VARARGS },
763 { "grey22grey", imageop_grey22grey, METH_VARARGS },
764 { "grey42grey", imageop_grey42grey, METH_VARARGS },
765 { "tovideo", imageop_tovideo, METH_VARARGS },
766 { "rgb2rgb8", imageop_rgb2rgb8, METH_VARARGS },
767 { "rgb82rgb", imageop_rgb82rgb, METH_VARARGS },
768 { "rgb2grey", imageop_rgb2grey, METH_VARARGS },
769 { "grey2rgb", imageop_grey2rgb, METH_VARARGS },
Roger E. Massea141f8a1996-12-20 20:50:39 +0000770 { 0, 0 }
Guido van Rossum0317a471992-10-26 13:40:15 +0000771};
772
773
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000774PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000775initimageop(void)
Guido van Rossum0317a471992-10-26 13:40:15 +0000776{
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000777 PyObject *m;
Roger E. Massea141f8a1996-12-20 20:50:39 +0000778 m = Py_InitModule("imageop", imageop_methods);
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000779 ImageopDict = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000780 ImageopError = PyErr_NewException("imageop.error", NULL, NULL);
781 if (ImageopError != NULL)
Sjoerd Mullender7e6bbe12004-01-10 20:43:43 +0000782 PyDict_SetItemString(ImageopDict, "error", ImageopError);
Guido van Rossum0317a471992-10-26 13:40:15 +0000783}