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 ( product % y == 0 ) { 54 product /= y; 55 if ( product % x == 0 && size == product / x ) 56 return 1; 57 } 58 PyErr_SetString(ImageopError, "String has incorrect length"); 59 return 0; 60} 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{ 69 return check_multiply_size(product, x, "x", y, "y", 1); 70} 71 72/* 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{ 92 static PyObject *bcos; 93 PyObject *bco; 94 long rc; 95 96 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 */ 116} 117 118static PyObject * 119imageop_crop(PyObject *self, PyObject *args) 120{ 121 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; 127 128 if ( !PyArg_ParseTuple(args, "s#iiiiiii", &cp, &len, &size, &x, &y, 129 &newx1, &newy1, &newx2, &newy2) ) 130 return 0; 131 132 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; 138 139 xstep = (newx1 < newx2)? 1 : -1; 140 ystep = (newy1 < newy2)? 1 : -1; 141 142 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; 171} 172 173static PyObject * 174imageop_scale(PyObject *self, PyObject *args) 175{ 176 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; 183 184 if ( !PyArg_ParseTuple(args, "s#iiiii", 185 &cp, &len, &size, &x, &y, &newx, &newy) ) 186 return 0; 187 188 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; 197 198 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; 217} 218 219/* Note: this routine can use a bit of optimizing */ 220 221static PyObject * 222imageop_tovideo(PyObject *self, PyObject *args) 223{ 224 int maxx, maxy, x, y, len; 225 int i; 226 unsigned char *cp, *ncp; 227 int width; 228 PyObject *rv; 229 230 231 if ( !PyArg_ParseTuple(args, "s#iii", &cp, &len, &width, &maxx, &maxy) ) 232 return 0; 233 234 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; 240 241 rv = PyString_FromStringAndSize(NULL, len); 242 if ( rv == 0 ) 243 return 0; 244 ncp = (unsigned char *)PyString_AsString(rv); 245 246 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; 271} 272 273static PyObject * 274imageop_grey2mono(PyObject *self, PyObject *args) 275{ 276 int tres, x, y, len; 277 unsigned char *cp, *ncp; 278 unsigned char ovalue; 279 PyObject *rv; 280 int i, bit; 281 282 283 if ( !PyArg_ParseTuple(args, "s#iii", &cp, &len, &x, &y, &tres) ) 284 return 0; 285 286 if ( !check_multiply(len, x, y) ) 287 return 0; 288 289 rv = PyString_FromStringAndSize(NULL, (len+7)/8); 290 if ( rv == 0 ) 291 return 0; 292 ncp = (unsigned char *)PyString_AsString(rv); 293 294 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; 309} 310 311static PyObject * 312imageop_grey2grey4(PyObject *self, PyObject *args) 313{ 314 int x, y, len; 315 unsigned char *cp, *ncp; 316 unsigned char ovalue; 317 PyObject *rv; 318 int i; 319 int pos; 320 321 322 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) 323 return 0; 324 325 if ( !check_multiply(len, x, y) ) 326 return 0; 327 328 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; 346} 347 348static PyObject * 349imageop_grey2grey2(PyObject *self, PyObject *args) 350{ 351 int x, y, len; 352 unsigned char *cp, *ncp; 353 unsigned char ovalue; 354 PyObject *rv; 355 int i; 356 int pos; 357 358 359 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) 360 return 0; 361 362 if ( !check_multiply(len, x, y) ) 363 return 0; 364 365 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; 383} 384 385static PyObject * 386imageop_dither2mono(PyObject *self, PyObject *args) 387{ 388 int sum, x, y, len; 389 unsigned char *cp, *ncp; 390 unsigned char ovalue; 391 PyObject *rv; 392 int i, bit; 393 394 395 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) 396 return 0; 397 398 if ( !check_multiply(len, x, y) ) 399 return 0; 400 401 rv = PyString_FromStringAndSize(NULL, (len+7)/8); 402 if ( rv == 0 ) 403 return 0; 404 ncp = (unsigned char *)PyString_AsString(rv); 405 406 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; 425} 426 427static PyObject * 428imageop_dither2grey2(PyObject *self, PyObject *args) 429{ 430 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; 437 438 439 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) 440 return 0; 441 442 if ( !check_multiply(len, x, y) ) 443 return 0; 444 445 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; 466} 467 468static PyObject * 469imageop_mono2grey(PyObject *self, PyObject *args) 470{ 471 int v0, v1, x, y, len, nlen; 472 unsigned char *cp, *ncp; 473 PyObject *rv; 474 int i, bit; 475 476 if ( !PyArg_ParseTuple(args, "s#iiii", &cp, &len, &x, &y, &v0, &v1) ) 477 return 0; 478 479 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 } 486 487 rv = PyString_FromStringAndSize(NULL, nlen); 488 if ( rv == 0 ) 489 return 0; 490 ncp = (unsigned char *)PyString_AsString(rv); 491 492 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; 505} 506 507static PyObject * 508imageop_grey22grey(PyObject *self, PyObject *args) 509{ 510 int x, y, len, nlen; 511 unsigned char *cp, *ncp; 512 PyObject *rv; 513 int i, pos, value = 0, nvalue; 514 515 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) 516 return 0; 517 518 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 } 526 527 rv = PyString_FromStringAndSize(NULL, nlen); 528 if ( rv == 0 ) 529 return 0; 530 ncp = (unsigned char *)PyString_AsString(rv); 531 532 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; 544} 545 546static PyObject * 547imageop_grey42grey(PyObject *self, PyObject *args) 548{ 549 int x, y, len, nlen; 550 unsigned char *cp, *ncp; 551 PyObject *rv; 552 int i, pos, value = 0, nvalue; 553 554 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) 555 return 0; 556 557 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 } 564 565 rv = PyString_FromStringAndSize(NULL, nlen); 566 if ( rv == 0 ) 567 return 0; 568 ncp = (unsigned char *)PyString_AsString(rv); 569 570 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; 581} 582 583static PyObject * 584imageop_rgb2rgb8(PyObject *self, PyObject *args) 585{ 586 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(); 592 593 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) 594 return 0; 595 596 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; 601 602 rv = PyString_FromStringAndSize(NULL, nlen); 603 if ( rv == 0 ) 604 return 0; 605 ncp = (unsigned char *)PyString_AsString(rv); 606 607 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; 624} 625 626static PyObject * 627imageop_rgb82rgb(PyObject *self, PyObject *args) 628{ 629 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(); 636 637 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) 638 return 0; 639 640 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; 645 646 rv = PyString_FromStringAndSize(NULL, nlen); 647 if ( rv == 0 ) 648 return 0; 649 ncp = (unsigned char *)PyString_AsString(rv); 650 651 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; 674} 675 676static PyObject * 677imageop_rgb2grey(PyObject *self, PyObject *args) 678{ 679 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(); 686 687 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) 688 return 0; 689 690 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; 695 696 rv = PyString_FromStringAndSize(NULL, nlen); 697 if ( rv == 0 ) 698 return 0; 699 ncp = (unsigned char *)PyString_AsString(rv); 700 701 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; 719} 720 721static PyObject * 722imageop_grey2rgb(PyObject *self, PyObject *args) 723{ 724 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(); 731 732 if ( !PyArg_ParseTuple(args, "s#ii", &cp, &len, &x, &y) ) 733 return 0; 734 735 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; 740 741 rv = PyString_FromStringAndSize(NULL, nlen); 742 if ( rv == 0 ) 743 return 0; 744 ncp = (unsigned char *)PyString_AsString(rv); 745 746 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; 759} 760 761static PyMethodDef imageop_methods[] = { 762 { "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 } 778}; 779 780 781PyMODINIT_FUNC 782initimageop(void) 783{ 784 PyObject *m; 785 786 if (PyErr_WarnPy3k("the imageop module has been removed in " 787 "Python 3.0", 2) < 0) 788 return; 789 790 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); 797} 798