home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Programming / Python2 / Python20_source / Modules / rgbimgmodule.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-25  |  16.4 KB  |  767 lines

  1. /*
  2.  *       fastimg -
  3.  *        Faster reading and writing of image files.
  4.  *
  5.  *      This code should work on machines with any byte order.
  6.  *
  7.  *    Could someone make this run real fast using multiple processors 
  8.  *    or how about using memory mapped files to speed it up?
  9.  *
  10.  *                Paul Haeberli - 1991
  11.  *
  12.  *    Changed to return sizes.
  13.  *                Sjoerd Mullender - 1993
  14.  *    Changed to incorporate into Python.
  15.  *                Sjoerd Mullender - 1993
  16.  */
  17. #include "Python.h"
  18.  
  19. #if SIZEOF_INT == 4
  20. typedef int Py_Int32;
  21. typedef unsigned int Py_UInt32;
  22. #else
  23. #if SIZEOF_LONG == 4
  24. typedef long Py_Int32;
  25. typedef unsigned long Py_UInt32;
  26. #else
  27. #error "No 4-byte integral type"
  28. #endif
  29. #endif
  30.  
  31. #ifdef HAVE_UNISTD_H
  32. #include <unistd.h>
  33. #endif
  34. #include <string.h>
  35.  
  36. /*
  37.  *    from image.h
  38.  *
  39.  */
  40. typedef struct {
  41.     unsigned short    imagic;        /* stuff saved on disk . . */
  42.     unsigned short     type;
  43.     unsigned short     dim;
  44.     unsigned short     xsize;
  45.     unsigned short     ysize;
  46.     unsigned short     zsize;
  47.     Py_UInt32     min;
  48.     Py_UInt32     max;
  49.     Py_UInt32    wastebytes;    
  50.     char         name[80];
  51.     Py_UInt32    colormap;
  52.  
  53.     Py_Int32    file;        /* stuff used in core only */
  54.     unsigned short     flags;
  55.     short        dorev;
  56.     short        x;
  57.     short        y;
  58.     short        z;
  59.     short        cnt;
  60.     unsigned short    *ptr;
  61.     unsigned short    *base;
  62.     unsigned short    *tmpbuf;
  63.     Py_UInt32    offset;
  64.     Py_UInt32    rleend;        /* for rle images */
  65.     Py_UInt32    *rowstart;    /* for rle images */
  66.     Py_Int32    *rowsize;    /* for rle images */
  67. } IMAGE;
  68.  
  69. #define IMAGIC     0732
  70.  
  71. #define TYPEMASK        0xff00
  72. #define BPPMASK            0x00ff
  73. #define ITYPE_VERBATIM        0x0000
  74. #define ITYPE_RLE        0x0100
  75. #define ISRLE(type)        (((type) & 0xff00) == ITYPE_RLE)
  76. #define ISVERBATIM(type)    (((type) & 0xff00) == ITYPE_VERBATIM)
  77. #define BPP(type)        ((type) & BPPMASK)
  78. #define RLE(bpp)        (ITYPE_RLE | (bpp))
  79. #define VERBATIM(bpp)        (ITYPE_VERBATIM | (bpp))
  80. /*
  81.  *    end of image.h stuff
  82.  *
  83.  */
  84.  
  85. #define RINTLUM (79)
  86. #define GINTLUM (156)
  87. #define BINTLUM (21)
  88.  
  89. #define ILUM(r,g,b)     ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8)
  90.  
  91. #define OFFSET_R    3    /* this is byte order dependent */
  92. #define OFFSET_G    2
  93. #define OFFSET_B    1
  94. #define OFFSET_A    0
  95.  
  96. #define CHANOFFSET(z)    (3-(z))    /* this is byte order dependent */
  97.  
  98. static void expandrow(unsigned char *, unsigned char *, int);
  99. static void setalpha(unsigned char *, int);
  100. static void copybw(Py_Int32 *, int);
  101. static void interleaverow(unsigned char*, unsigned char*, int, int);
  102. static int compressrow(unsigned char *, unsigned char *, int, int);
  103. static void lumrow(unsigned char *, unsigned char *, int);
  104.  
  105. #ifdef ADD_TAGS
  106. #define TAGLEN    (5)
  107. #else
  108. #define TAGLEN    (0)
  109. #endif
  110.  
  111. static PyObject *ImgfileError;
  112.  
  113. static int reverse_order;
  114.  
  115. #ifdef ADD_TAGS
  116. /*
  117.  *    addlongimgtag - 
  118.  *        this is used to extract image data from core dumps.
  119.  *
  120.  */
  121. static void 
  122. addlongimgtag(Py_UInt32 *dptr, int xsize, int ysize)
  123. {
  124.     dptr = dptr + (xsize * ysize);
  125.     dptr[0] = 0x12345678;
  126.     dptr[1] = 0x59493333;
  127.     dptr[2] = 0x69434222;
  128.     dptr[3] = xsize;
  129.     dptr[4] = ysize;
  130. }
  131. #endif
  132.  
  133. /*
  134.  *    byte order independent read/write of shorts and longs.
  135.  *
  136.  */
  137. static unsigned short
  138. getshort(FILE *inf)
  139. {
  140.     unsigned char buf[2];
  141.  
  142.     fread(buf, 2, 1, inf);
  143.     return (buf[0] << 8) + (buf[1] << 0);
  144. }
  145.  
  146. static Py_UInt32
  147. getlong(FILE *inf)
  148. {
  149.     unsigned char buf[4];
  150.  
  151.     fread(buf, 4, 1, inf);
  152.     return (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + (buf[3] << 0);
  153. }
  154.  
  155. static void
  156. putshort(FILE *outf, unsigned short val)
  157. {
  158.     unsigned char buf[2];
  159.  
  160.     buf[0] = (val >> 8);
  161.     buf[1] = (val >> 0);
  162.     fwrite(buf, 2, 1, outf);
  163. }
  164.  
  165. static int
  166. putlong(FILE *outf, Py_UInt32 val)
  167. {
  168.     unsigned char buf[4];
  169.  
  170.     buf[0] = (unsigned char) (val >> 24);
  171.     buf[1] = (unsigned char) (val >> 16);
  172.     buf[2] = (unsigned char) (val >> 8);
  173.     buf[3] = (unsigned char) (val >> 0);
  174.     return fwrite(buf, 4, 1, outf);
  175. }
  176.  
  177. static void
  178. readheader(FILE *inf, IMAGE *image)
  179. {
  180.     memset(image ,0, sizeof(IMAGE));
  181.     image->imagic = getshort(inf);
  182.     image->type   = getshort(inf);
  183.     image->dim    = getshort(inf);
  184.     image->xsize  = getshort(inf);
  185.     image->ysize  = getshort(inf);
  186.     image->zsize  = getshort(inf);
  187. }
  188.  
  189. static int
  190. writeheader(FILE *outf, IMAGE *image)
  191. {
  192.     IMAGE t;
  193.  
  194.     memset(&t, 0, sizeof(IMAGE));
  195.     fwrite(&t, sizeof(IMAGE), 1, outf);
  196.     fseek(outf, 0, SEEK_SET);
  197.     putshort(outf, image->imagic);
  198.     putshort(outf, image->type);
  199.     putshort(outf, image->dim);
  200.     putshort(outf, image->xsize);
  201.     putshort(outf, image->ysize);
  202.     putshort(outf, image->zsize);
  203.     putlong(outf, image->min);
  204.     putlong(outf, image->max);
  205.     putlong(outf, 0);
  206.     return fwrite("no name", 8, 1, outf);
  207. }
  208.  
  209. static int
  210. writetab(FILE *outf, /*unsigned*/ Py_Int32 *tab, int len)
  211. {
  212.     int r = 0;
  213.  
  214.     while(len) {
  215.         r = putlong(outf, *tab++);
  216.         len--;
  217.     }
  218.     return r;
  219. }
  220.  
  221. static void
  222. readtab(FILE *inf, /*unsigned*/ Py_Int32 *tab, int len)
  223. {
  224.     while(len) {
  225.         *tab++ = getlong(inf);
  226.         len--;
  227.     }
  228. }
  229.  
  230. /*
  231.  *    sizeofimage - 
  232.  *        return the xsize and ysize of an iris image file.
  233.  *
  234.  */
  235. static PyObject *
  236. sizeofimage(PyObject *self, PyObject *args)
  237. {
  238.     char *name;
  239.     IMAGE image;
  240.     FILE *inf;
  241.  
  242.     if (!PyArg_Parse(args, "s", &name))
  243.         return NULL;
  244.  
  245.     inf = fopen(name, "rb");
  246.     if (!inf) {
  247.         PyErr_SetString(ImgfileError, "can't open image file");
  248.         return NULL;
  249.     }
  250.     readheader(inf, &image);
  251.     fclose(inf);
  252.     if (image.imagic != IMAGIC) {
  253.         PyErr_SetString(ImgfileError,
  254.                 "bad magic number in image file");
  255.         return NULL;
  256.     }
  257.     return Py_BuildValue("(ii)", image.xsize, image.ysize);
  258. }
  259.  
  260. /*
  261.  *    longimagedata - 
  262.  *        read in a B/W RGB or RGBA iris image file and return a 
  263.  *    pointer to an array of longs.
  264.  *
  265.  */
  266. static PyObject *
  267. longimagedata(PyObject *self, PyObject *args)
  268. {
  269.     char *name;
  270.     unsigned char *base, *lptr;
  271.     unsigned char *rledat = NULL, *verdat = NULL;
  272.     Py_Int32 *starttab = NULL, *lengthtab = NULL;
  273.     FILE *inf = NULL;
  274.     IMAGE image;
  275.     int y, z, tablen;
  276.     int xsize, ysize, zsize;
  277.     int bpp, rle, cur, badorder;
  278.     int rlebuflen;
  279.     PyObject *rv = NULL;
  280.  
  281.     if (!PyArg_Parse(args, "s", &name))
  282.         return NULL;
  283.  
  284.     inf = fopen(name,"rb");
  285.     if (!inf) {
  286.         PyErr_SetString(ImgfileError, "can't open image file");
  287.         return NULL;
  288.     }
  289.     readheader(inf,&image);
  290.     if (image.imagic != IMAGIC) {
  291.         PyErr_SetString(ImgfileError,
  292.                 "bad magic number in image file");
  293.         goto finally;
  294.     }
  295.     rle = ISRLE(image.type);
  296.     bpp = BPP(image.type);
  297.     if (bpp != 1) {
  298.         PyErr_SetString(ImgfileError,
  299.                 "image must have 1 byte per pix chan");
  300.         goto finally;
  301.     }
  302.     xsize = image.xsize;
  303.     ysize = image.ysize;
  304.     zsize = image.zsize;
  305.     if (rle) {
  306.         tablen = ysize * zsize * sizeof(Py_Int32);
  307.         starttab = (Py_Int32 *)malloc(tablen);
  308.         lengthtab = (Py_Int32 *)malloc(tablen);
  309.         rlebuflen = (int) (1.05 * xsize +10);
  310.         rledat = (unsigned char *)malloc(rlebuflen);
  311.         if (!starttab || !lengthtab || !rledat) {
  312.             PyErr_NoMemory();
  313.             goto finally;
  314.         }
  315.         
  316.         fseek(inf, 512, SEEK_SET);
  317.         readtab(inf, starttab, ysize*zsize);
  318.         readtab(inf, lengthtab, ysize*zsize);
  319.  
  320.         /* check data order */
  321.         cur = 0;
  322.         badorder = 0;
  323.         for(y = 0; y < ysize; y++) {
  324.             for(z = 0; z < zsize; z++) {
  325.                 if (starttab[y + z * ysize] < cur) {
  326.                     badorder = 1;
  327.                     break;
  328.                 }
  329.                 cur = starttab[y +z * ysize];
  330.             }
  331.             if (badorder)
  332.                 break;
  333.         }
  334.  
  335.         fseek(inf, 512 + 2 * tablen, SEEK_SET);
  336.         cur = 512 + 2 * tablen;
  337.         rv = PyString_FromStringAndSize((char *)NULL,
  338.                       (xsize * ysize + TAGLEN) * sizeof(Py_Int32));
  339.         if (rv == NULL)
  340.             goto finally;
  341.  
  342.         base = (unsigned char *) PyString_AsString(rv);
  343. #ifdef ADD_TAGS
  344.         addlongimgtag(base,xsize,ysize);
  345. #endif
  346.         if (badorder) {
  347.             for (z = 0; z < zsize; z++) {
  348.                 lptr = base;
  349.                 if (reverse_order)
  350.                     lptr += (ysize - 1) * xsize
  351.                         * sizeof(Py_UInt32);
  352.                 for (y = 0; y < ysize; y++) {
  353.                     int idx = y + z * ysize;
  354.                     if (cur != starttab[idx]) {
  355.                         fseek(inf,starttab[idx],
  356.                               SEEK_SET);
  357.                         cur = starttab[idx];
  358.                     }
  359.                     if (lengthtab[idx] > rlebuflen) {
  360.                         PyErr_SetString(ImgfileError,
  361.                             "rlebuf is too small");
  362.                         Py_DECREF(rv);
  363.                         rv = NULL;
  364.                         goto finally;
  365.                     }
  366.                     fread(rledat, lengthtab[idx], 1, inf);
  367.                     cur += lengthtab[idx];
  368.                     expandrow(lptr, rledat, 3-z);
  369.                     if (reverse_order)
  370.                         lptr -= xsize
  371.                               * sizeof(Py_UInt32);
  372.                     else
  373.                         lptr += xsize
  374.                               * sizeof(Py_UInt32);
  375.                 }
  376.             }
  377.         } else {
  378.             lptr = base;
  379.             if (reverse_order)
  380.                 lptr += (ysize - 1) * xsize
  381.                     * sizeof(Py_UInt32);
  382.             for (y = 0; y < ysize; y++) {
  383.                 for(z = 0; z < zsize; z++) {
  384.                     int idx = y + z * ysize;
  385.                     if (cur != starttab[idx]) {
  386.                         fseek(inf, starttab[idx],
  387.                               SEEK_SET);
  388.                         cur = starttab[idx];
  389.                     }
  390.                     fread(rledat, lengthtab[idx], 1, inf);
  391.                     cur += lengthtab[idx];
  392.                     expandrow(lptr, rledat, 3-z);
  393.                 }
  394.                 if (reverse_order)
  395.                     lptr -= xsize * sizeof(Py_UInt32);
  396.                 else
  397.                     lptr += xsize * sizeof(Py_UInt32);
  398.             }
  399.         }
  400.         if (zsize == 3) 
  401.             setalpha(base, xsize * ysize);
  402.         else if (zsize < 3) 
  403.             copybw((Py_Int32 *) base, xsize * ysize);
  404.     }
  405.     else {
  406.         rv = PyString_FromStringAndSize((char *) 0,
  407.                        (xsize*ysize+TAGLEN)*sizeof(Py_Int32));
  408.         if (rv == NULL)
  409.             goto finally;
  410.  
  411.         base = (unsigned char *) PyString_AsString(rv);
  412. #ifdef ADD_TAGS
  413.         addlongimgtag(base, xsize, ysize);
  414. #endif
  415.         verdat = (unsigned char *)malloc(xsize);
  416.         fseek(inf, 512, SEEK_SET);
  417.         for (z = 0; z < zsize; z++) {
  418.             lptr = base;
  419.             if (reverse_order)
  420.                 lptr += (ysize - 1) * xsize
  421.                         * sizeof(Py_UInt32);
  422.             for (y = 0; y < ysize; y++) {
  423.                 fread(verdat, xsize, 1, inf);
  424.                 interleaverow(lptr, verdat, 3-z, xsize);
  425.                 if (reverse_order)
  426.                     lptr -= xsize * sizeof(Py_UInt32);
  427.                 else
  428.                     lptr += xsize * sizeof(Py_UInt32);
  429.             }
  430.         }
  431.         if (zsize == 3)
  432.             setalpha(base, xsize * ysize);
  433.         else if (zsize < 3) 
  434.             copybw((Py_Int32 *) base, xsize * ysize);
  435.     }
  436.   finally:
  437.     free(starttab);
  438.     free(lengthtab);
  439.     free(rledat);
  440.     free(verdat);
  441.     fclose(inf);
  442.     return rv;
  443. }
  444.  
  445. /* static utility functions for longimagedata */
  446.  
  447. static void
  448. interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n)
  449. {
  450.     lptr += z;
  451.     while (n--) {
  452.         *lptr = *cptr++;
  453.         lptr += 4;
  454.     }
  455. }
  456.  
  457. static void
  458. copybw(Py_Int32 *lptr, int n)
  459. {
  460.     while (n >= 8) {
  461.         lptr[0] = 0xff000000 + (0x010101 * (lptr[0] & 0xff));
  462.         lptr[1] = 0xff000000 + (0x010101 * (lptr[1] & 0xff));
  463.         lptr[2] = 0xff000000 + (0x010101 * (lptr[2] & 0xff));
  464.         lptr[3] = 0xff000000 + (0x010101 * (lptr[3] & 0xff));
  465.         lptr[4] = 0xff000000 + (0x010101 * (lptr[4] & 0xff));
  466.         lptr[5] = 0xff000000 + (0x010101 * (lptr[5] & 0xff));
  467.         lptr[6] = 0xff000000 + (0x010101 * (lptr[6] & 0xff));
  468.         lptr[7] = 0xff000000 + (0x010101 * (lptr[7] & 0xff));
  469.         lptr += 8;
  470.         n -= 8;
  471.     }
  472.     while (n--) {
  473.         *lptr = 0xff000000 + (0x010101 * (*lptr&0xff));
  474.         lptr++;
  475.     }
  476. }
  477.  
  478. static void
  479. setalpha(unsigned char *lptr, int n)
  480. {
  481.     while (n >= 8) {
  482.         lptr[0 * 4] = 0xff;
  483.         lptr[1 * 4] = 0xff;
  484.         lptr[2 * 4] = 0xff;
  485.         lptr[3 * 4] = 0xff;
  486.         lptr[4 * 4] = 0xff;
  487.         lptr[5 * 4] = 0xff;
  488.         lptr[6 * 4] = 0xff;
  489.         lptr[7 * 4] = 0xff;
  490.         lptr += 4 * 8;
  491.         n -= 8;
  492.     }
  493.     while (n--) {
  494.         *lptr = 0xff;
  495.         lptr += 4;
  496.     }
  497. }
  498.  
  499. static void
  500. expandrow(unsigned char *optr, unsigned char *iptr, int z)
  501. {
  502.     unsigned char pixel, count;
  503.  
  504.     optr += z;
  505.     while (1) {
  506.         pixel = *iptr++;
  507.         if (!(count = (pixel & 0x7f)))
  508.             return;
  509.         if (pixel & 0x80) {
  510.             while (count >= 8) {
  511.                 optr[0 * 4] = iptr[0];
  512.                 optr[1 * 4] = iptr[1];
  513.                 optr[2 * 4] = iptr[2];
  514.                 optr[3 * 4] = iptr[3];
  515.                 optr[4 * 4] = iptr[4];
  516.                 optr[5 * 4] = iptr[5];
  517.                 optr[6 * 4] = iptr[6];
  518.                 optr[7 * 4] = iptr[7];
  519.                 optr += 8 * 4;
  520.                 iptr += 8;
  521.                 count -= 8;
  522.             }
  523.             while (count--) {
  524.                 *optr = *iptr++;
  525.                 optr += 4;
  526.             }
  527.         }
  528.         else {
  529.             pixel = *iptr++;
  530.             while (count >= 8) {
  531.                 optr[0 * 4] = pixel;
  532.                 optr[1 * 4] = pixel;
  533.                 optr[2 * 4] = pixel;
  534.                 optr[3 * 4] = pixel;
  535.                 optr[4 * 4] = pixel;
  536.                 optr[5 * 4] = pixel;
  537.                 optr[6 * 4] = pixel;
  538.                 optr[7 * 4] = pixel;
  539.                 optr += 8 * 4;
  540.                 count -= 8;
  541.             }
  542.             while (count--) {
  543.                 *optr = pixel;
  544.                 optr += 4;
  545.             }
  546.         }
  547.     }
  548. }
  549.  
  550. /*
  551.  *    longstoimage -
  552.  *        copy an array of longs to an iris image file.  Each long
  553.  *    represents one pixel.  xsize and ysize specify the dimensions of
  554.  *    the pixel array.  zsize specifies what kind of image file to
  555.  *    write out.  if zsize is 1, the luminance of the pixels are
  556.  *    calculated, and a single channel black and white image is saved.
  557.  *    If zsize is 3, an RGB image file is saved.  If zsize is 4, an
  558.  *    RGBA image file is saved.
  559.  *
  560.  */
  561. static PyObject *
  562. longstoimage(PyObject *self, PyObject *args)
  563. {
  564.     unsigned char *lptr;
  565.     char *name;
  566.     int xsize, ysize, zsize;
  567.     FILE *outf = NULL;
  568.     IMAGE image;
  569.     int tablen, y, z, pos, len;
  570.     Py_Int32 *starttab = NULL, *lengthtab = NULL;
  571.     unsigned char *rlebuf = NULL;
  572.     unsigned char *lumbuf = NULL;
  573.     int rlebuflen, goodwrite;
  574.     PyObject *retval = NULL;
  575.  
  576.     if (!PyArg_Parse(args, "(s#iiis)", &lptr, &len, &xsize, &ysize, &zsize,
  577.              &name))
  578.         return NULL;
  579.  
  580.     goodwrite = 1;
  581.     outf = fopen(name, "wb");
  582.     if (!outf) {
  583.         PyErr_SetString(ImgfileError, "can't open output file");
  584.         return NULL;
  585.     }
  586.     tablen = ysize * zsize * sizeof(Py_Int32);
  587.  
  588.     starttab = (Py_Int32 *)malloc(tablen);
  589.     lengthtab = (Py_Int32 *)malloc(tablen);
  590.     rlebuflen = (int) (1.05 * xsize + 10);
  591.     rlebuf = (unsigned char *)malloc(rlebuflen);
  592.     lumbuf = (unsigned char *)malloc(xsize * sizeof(Py_Int32));
  593.     if (!starttab || !lengthtab || !rlebuf || !lumbuf) {
  594.         PyErr_NoMemory();
  595.         goto finally;
  596.     }
  597.     
  598.     memset(&image, 0, sizeof(IMAGE));
  599.     image.imagic = IMAGIC; 
  600.     image.type = RLE(1);
  601.     if (zsize>1)
  602.         image.dim = 3;
  603.     else
  604.         image.dim = 2;
  605.     image.xsize = xsize;
  606.     image.ysize = ysize;
  607.     image.zsize = zsize;
  608.     image.min = 0;
  609.     image.max = 255;
  610.     goodwrite *= writeheader(outf, &image);
  611.     pos = 512 + 2 * tablen;
  612.     fseek(outf, pos, SEEK_SET);
  613.     if (reverse_order)
  614.         lptr += (ysize - 1) * xsize * sizeof(Py_UInt32);
  615.     for (y = 0; y < ysize; y++) {
  616.         for (z = 0; z < zsize; z++) {
  617.             if (zsize == 1) {
  618.                 lumrow(lptr, lumbuf, xsize);
  619.                 len = compressrow(lumbuf, rlebuf,
  620.                           CHANOFFSET(z), xsize);
  621.             } else {
  622.                 len = compressrow(lptr, rlebuf,
  623.                           CHANOFFSET(z), xsize);
  624.             }
  625.             if(len > rlebuflen) {
  626.                 PyErr_SetString(ImgfileError,
  627.                         "rlebuf is too small");
  628.                 goto finally;
  629.             }
  630.             goodwrite *= fwrite(rlebuf, len, 1, outf);
  631.             starttab[y + z * ysize] = pos;
  632.             lengthtab[y + z * ysize] = len;
  633.             pos += len;
  634.         }
  635.         if (reverse_order)
  636.             lptr -= xsize * sizeof(Py_UInt32);
  637.         else
  638.             lptr += xsize * sizeof(Py_UInt32);
  639.     }
  640.  
  641.     fseek(outf, 512, SEEK_SET);
  642.     goodwrite *= writetab(outf, starttab, ysize*zsize);
  643.     goodwrite *= writetab(outf, lengthtab, ysize*zsize);
  644.     if (goodwrite) {
  645.         Py_INCREF(Py_None);
  646.         retval = Py_None;
  647.     } else
  648.         PyErr_SetString(ImgfileError, "not enough space for image");
  649.  
  650.   finally:
  651.     fclose(outf);
  652.     free(starttab);
  653.     free(lengthtab);
  654.     free(rlebuf);
  655.     free(lumbuf);
  656.     return retval;
  657. }
  658.  
  659. /* static utility functions for longstoimage */
  660.  
  661. static void
  662. lumrow(unsigned char *rgbptr, unsigned char *lumptr, int n)
  663. {
  664.     lumptr += CHANOFFSET(0);
  665.     while (n--) {
  666.         *lumptr = ILUM(rgbptr[OFFSET_R],
  667.                    rgbptr[OFFSET_G],
  668.                    rgbptr[OFFSET_B]);
  669.         lumptr += 4;
  670.         rgbptr += 4;
  671.     }
  672. }
  673.  
  674. static int
  675. compressrow(unsigned char *lbuf, unsigned char *rlebuf, int z, int cnt)
  676. {
  677.     unsigned char *iptr, *ibufend, *sptr, *optr;
  678.     short todo, cc;                            
  679.     Py_Int32 count;
  680.  
  681.     lbuf += z;
  682.     iptr = lbuf;
  683.     ibufend = iptr + cnt * 4;
  684.     optr = rlebuf;
  685.  
  686.     while(iptr < ibufend) {
  687.         sptr = iptr;
  688.         iptr += 8;
  689.         while ((iptr<ibufend) &&
  690.                ((iptr[-8]!=iptr[-4]) ||(iptr[-4]!=iptr[0])))
  691.         {
  692.             iptr += 4;
  693.         }
  694.         iptr -= 8;
  695.         count = (iptr - sptr) / 4;
  696.         while (count) {
  697.             todo = count > 126 ? 126 : (short)count;
  698.             count -= todo;
  699.             *optr++ = 0x80 | todo;
  700.             while (todo > 8) {
  701.                 optr[0] = sptr[0 * 4];
  702.                 optr[1] = sptr[1 * 4];
  703.                 optr[2] = sptr[2 * 4];
  704.                 optr[3] = sptr[3 * 4];
  705.                 optr[4] = sptr[4 * 4];
  706.                 optr[5] = sptr[5 * 4];
  707.                 optr[6] = sptr[6 * 4];
  708.                 optr[7] = sptr[7 * 4];
  709.                 optr += 8;
  710.                 sptr += 8 * 4;
  711.                 todo -= 8;
  712.             }
  713.             while (todo--) {
  714.                 *optr++ = *sptr;
  715.                 sptr += 4;
  716.             }
  717.         }
  718.         sptr = iptr;
  719.         cc = *iptr;
  720.         iptr += 4;
  721.         while ((iptr < ibufend) && (*iptr == cc))
  722.             iptr += 4;
  723.         count = (iptr - sptr) / 4;
  724.         while (count) {
  725.             todo = count > 126 ? 126 : (short)count;
  726.             count -= todo;
  727.             *optr++ = (unsigned char) todo;
  728.             *optr++ = (unsigned char) cc;
  729.         }
  730.     }
  731.     *optr++ = 0;
  732.     return optr - (unsigned char *)rlebuf;
  733. }
  734.  
  735. static PyObject *
  736. ttob(PyObject *self, PyObject *args)
  737. {
  738.     int order, oldorder;
  739.  
  740.     if (!PyArg_Parse(args, "i", &order))
  741.         return NULL;
  742.     oldorder = reverse_order;
  743.     reverse_order = order;
  744.     return PyInt_FromLong(oldorder);
  745. }
  746.  
  747. static PyMethodDef
  748. rgbimg_methods[] = {
  749.     {"sizeofimage",       sizeofimage},
  750.     {"longimagedata",  longimagedata},
  751.     {"longstoimage",   longstoimage},
  752.     {"ttob",       ttob},
  753.     {NULL,             NULL}         /* sentinel */
  754. };
  755.  
  756.  
  757. DL_EXPORT(void)
  758. initrgbimg(void)
  759. {
  760.     PyObject *m, *d;
  761.     m = Py_InitModule("rgbimg", rgbimg_methods);
  762.     d = PyModule_GetDict(m);
  763.     ImgfileError = PyErr_NewException("rgbimg.error", NULL, NULL);
  764.     if (ImgfileError != NULL)
  765.         PyDict_SetItemString(d, "error", ImgfileError);
  766. }
  767.