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