PageRenderTime 430ms CodeModel.GetById 141ms app.highlight 209ms RepoModel.GetById 72ms app.codeStats 1ms

/Modules/imageop.c

http://unladen-swallow.googlecode.com/
C | 794 lines | 663 code | 95 blank | 36 comment | 191 complexity | 573179c5071e8f44f6d548913925e645 MD5 | raw file
  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
 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
 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
 26static PyObject *ImageopError;
 27static PyObject *ImageopDict;
 28
 29/**
 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{
 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 */
 46static int
 47check_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 */
 63static int
 64check_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
 86static int
 87imageop_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
115static PyObject *
116imageop_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
170static PyObject *
171imageop_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
218static PyObject *
219imageop_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
270static PyObject *
271imageop_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
308static PyObject *
309imageop_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
345static PyObject *
346imageop_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
382static PyObject *
383imageop_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
424static PyObject *
425imageop_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
465static PyObject *
466imageop_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
504static PyObject *
505imageop_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
543static PyObject *
544imageop_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
580static PyObject *
581imageop_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
623static PyObject *
624imageop_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
673static PyObject *
674imageop_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
718static PyObject *
719imageop_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
758static 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
778PyMODINIT_FUNC
779initimageop(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}