home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / py2s152.zip / Modules / rgbimgmodule.c < prev    next >
C/C++ Source or Header  |  1999-06-27  |  18KB  |  801 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 Py_PROTO((unsigned char *, unsigned char *, int));
  99. static void setalpha Py_PROTO((unsigned char *, int));
  100. static void copybw Py_PROTO((Py_Int32 *, int));
  101. static void interleaverow Py_PROTO((unsigned char*, unsigned char*, int, int));
  102. static int compressrow Py_PROTO((unsigned char *, unsigned char *, int, int));
  103. static void lumrow Py_PROTO((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(dptr, xsize, ysize)
  123.     Py_UInt32 *dptr;
  124.     int xsize, ysize;
  125. {
  126.     dptr = dptr + (xsize * ysize);
  127.     dptr[0] = 0x12345678;
  128.     dptr[1] = 0x59493333;
  129.     dptr[2] = 0x69434222;
  130.     dptr[3] = xsize;
  131.     dptr[4] = ysize;
  132. }
  133. #endif
  134.  
  135. /*
  136.  *    byte order independent read/write of shorts and longs.
  137.  *
  138.  */
  139. static unsigned short
  140. getshort(inf)
  141.     FILE *inf;
  142. {
  143.     unsigned char buf[2];
  144.  
  145.     fread(buf, 2, 1, inf);
  146.     return (buf[0] << 8) + (buf[1] << 0);
  147. }
  148.  
  149. static Py_UInt32
  150. getlong(inf)
  151.     FILE *inf;
  152. {
  153.     unsigned char buf[4];
  154.  
  155.     fread(buf, 4, 1, inf);
  156.     return (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + (buf[3] << 0);
  157. }
  158.  
  159. static void
  160. putshort(outf, val)
  161.     FILE *outf;
  162.     unsigned short val;
  163. {
  164.     unsigned char buf[2];
  165.  
  166.     buf[0] = (val >> 8);
  167.     buf[1] = (val >> 0);
  168.     fwrite(buf, 2, 1, outf);
  169. }
  170.  
  171. static int
  172. putlong(outf, val)
  173.     FILE *outf;
  174.     Py_UInt32 val;
  175. {
  176.     unsigned char buf[4];
  177.  
  178.     buf[0] = (unsigned char) (val >> 24);
  179.     buf[1] = (unsigned char) (val >> 16);
  180.     buf[2] = (unsigned char) (val >> 8);
  181.     buf[3] = (unsigned char) (val >> 0);
  182.     return fwrite(buf, 4, 1, outf);
  183. }
  184.  
  185. static void
  186. readheader(inf, image)
  187.     FILE *inf;
  188.     IMAGE *image;
  189. {
  190.     memset(image ,0, sizeof(IMAGE));
  191.     image->imagic = getshort(inf);
  192.     image->type   = getshort(inf);
  193.     image->dim    = getshort(inf);
  194.     image->xsize  = getshort(inf);
  195.     image->ysize  = getshort(inf);
  196.     image->zsize  = getshort(inf);
  197. }
  198.  
  199. static int
  200. writeheader(outf, image)
  201.     FILE *outf;
  202.     IMAGE *image;
  203. {
  204.     IMAGE t;
  205.  
  206.     memset(&t, 0, sizeof(IMAGE));
  207.     fwrite(&t, sizeof(IMAGE), 1, outf);
  208.     fseek(outf, 0, SEEK_SET);
  209.     putshort(outf, image->imagic);
  210.     putshort(outf, image->type);
  211.     putshort(outf, image->dim);
  212.     putshort(outf, image->xsize);
  213.     putshort(outf, image->ysize);
  214.     putshort(outf, image->zsize);
  215.     putlong(outf, image->min);
  216.     putlong(outf, image->max);
  217.     putlong(outf, 0);
  218.     return fwrite("no name", 8, 1, outf);
  219. }
  220.  
  221. static int
  222. writetab(outf, tab, len)
  223.     FILE *outf;
  224.     /*unsigned*/ Py_Int32 *tab;
  225.     int len;
  226. {
  227.     int r = 0;
  228.  
  229.     while(len) {
  230.         r = putlong(outf, *tab++);
  231.         len--;
  232.     }
  233.     return r;
  234. }
  235.  
  236. static void
  237. readtab(inf, tab, len)
  238.     FILE *inf;
  239.     /*unsigned*/ Py_Int32 *tab;
  240.     int len;
  241. {
  242.     while(len) {
  243.         *tab++ = getlong(inf);
  244.         len--;
  245.     }
  246. }
  247.  
  248. /*
  249.  *    sizeofimage - 
  250.  *        return the xsize and ysize of an iris image file.
  251.  *
  252.  */
  253. static PyObject *
  254. sizeofimage(self, args)
  255.     PyObject *self, *args;
  256. {
  257.     char *name;
  258.     IMAGE image;
  259.     FILE *inf;
  260.  
  261.     if (!PyArg_Parse(args, "s", &name))
  262.         return NULL;
  263.  
  264.     inf = fopen(name, "rb");
  265.     if (!inf) {
  266.         PyErr_SetString(ImgfileError, "can't open image file");
  267.         return NULL;
  268.     }
  269.     readheader(inf, &image);
  270.     fclose(inf);
  271.     if (image.imagic != IMAGIC) {
  272.         PyErr_SetString(ImgfileError,
  273.                 "bad magic number in image file");
  274.         return NULL;
  275.     }
  276.     return Py_BuildValue("(ii)", image.xsize, image.ysize);
  277. }
  278.  
  279. /*
  280.  *    longimagedata - 
  281.  *        read in a B/W RGB or RGBA iris image file and return a 
  282.  *    pointer to an array of longs.
  283.  *
  284.  */
  285. static PyObject *
  286. longimagedata(self, args)
  287.     PyObject *self, *args;
  288. {
  289.     char *name;
  290.     unsigned char *base, *lptr;
  291.     unsigned char *rledat = NULL, *verdat = NULL;
  292.     Py_Int32 *starttab = NULL, *lengthtab = NULL;
  293.     FILE *inf = NULL;
  294.     IMAGE image;
  295.     int y, z, tablen;
  296.     int xsize, ysize, zsize;
  297.     int bpp, rle, cur, badorder;
  298.     int rlebuflen;
  299.     PyObject *rv = NULL;
  300.  
  301.     if (!PyArg_Parse(args, "s", &name))
  302.         return NULL;
  303.  
  304.     inf = fopen(name,"rb");
  305.     if (!inf) {
  306.         PyErr_SetString(ImgfileError, "can't open image file");
  307.         return NULL;
  308.     }
  309.     readheader(inf,&image);
  310.     if (image.imagic != IMAGIC) {
  311.         PyErr_SetString(ImgfileError,
  312.                 "bad magic number in image file");
  313.         goto finally;
  314.     }
  315.     rle = ISRLE(image.type);
  316.     bpp = BPP(image.type);
  317.     if (bpp != 1) {
  318.         PyErr_SetString(ImgfileError,
  319.                 "image must have 1 byte per pix chan");
  320.         goto finally;
  321.     }
  322.     xsize = image.xsize;
  323.     ysize = image.ysize;
  324.     zsize = image.zsize;
  325.     if (rle) {
  326.         tablen = ysize * zsize * sizeof(Py_Int32);
  327.         starttab = (Py_Int32 *)malloc(tablen);
  328.         lengthtab = (Py_Int32 *)malloc(tablen);
  329.         rlebuflen = (int) (1.05 * xsize +10);
  330.         rledat = (unsigned char *)malloc(rlebuflen);
  331.         if (!starttab || !lengthtab || !rledat) {
  332.             PyErr_NoMemory();
  333.             goto finally;
  334.         }
  335.         
  336.         fseek(inf, 512, SEEK_SET);
  337.         readtab(inf, starttab, ysize*zsize);
  338.         readtab(inf, lengthtab, ysize*zsize);
  339.  
  340.         /* check data order */
  341.         cur = 0;
  342.         badorder = 0;
  343.         for(y = 0; y < ysize; y++) {
  344.             for(z = 0; z < zsize; z++) {
  345.                 if (starttab[y + z * ysize] < cur) {
  346.                     badorder = 1;
  347.                     break;
  348.                 }
  349.                 cur = starttab[y +z * ysize];
  350.             }
  351.             if (badorder)
  352.                 break;
  353.         }
  354.  
  355.         fseek(inf, 512 + 2 * tablen, SEEK_SET);
  356.         cur = 512 + 2 * tablen;
  357.         rv = PyString_FromStringAndSize((char *)NULL,
  358.                       (xsize * ysize + TAGLEN) * sizeof(Py_Int32));
  359.         if (rv == NULL)
  360.             goto finally;
  361.  
  362.         base = (unsigned char *) PyString_AsString(rv);
  363. #ifdef ADD_TAGS
  364.         addlongimgtag(base,xsize,ysize);
  365. #endif
  366.         if (badorder) {
  367.             for (z = 0; z < zsize; z++) {
  368.                 lptr = base;
  369.                 if (reverse_order)
  370.                     lptr += (ysize - 1) * xsize
  371.                         * sizeof(Py_UInt32);
  372.                 for (y = 0; y < ysize; y++) {
  373.                     int idx = y + z * ysize;
  374.                     if (cur != starttab[idx]) {
  375.                         fseek(inf,starttab[idx],
  376.                               SEEK_SET);
  377.                         cur = starttab[idx];
  378.                     }
  379.                     if (lengthtab[idx] > rlebuflen) {
  380.                         PyErr_SetString(ImgfileError,
  381.                             "rlebuf is too small");
  382.                         Py_DECREF(rv);
  383.                         rv = NULL;
  384.                         goto finally;
  385.                     }
  386.                     fread(rledat, lengthtab[idx], 1, inf);
  387.                     cur += lengthtab[idx];
  388.                     expandrow(lptr, rledat, 3-z);
  389.                     if (reverse_order)
  390.                         lptr -= xsize
  391.                               * sizeof(Py_UInt32);
  392.                     else
  393.                         lptr += xsize
  394.                               * sizeof(Py_UInt32);
  395.                 }
  396.             }
  397.         } else {
  398.             lptr = base;
  399.             if (reverse_order)
  400.                 lptr += (ysize - 1) * xsize
  401.                     * sizeof(Py_UInt32);
  402.             for (y = 0; y < ysize; y++) {
  403.                 for(z = 0; z < zsize; z++) {
  404.                     int idx = y + z * ysize;
  405.                     if (cur != starttab[idx]) {
  406.                         fseek(inf, starttab[idx],
  407.                               SEEK_SET);
  408.                         cur = starttab[idx];
  409.                     }
  410.                     fread(rledat, lengthtab[idx], 1, inf);
  411.                     cur += lengthtab[idx];
  412.                     expandrow(lptr, rledat, 3-z);
  413.                 }
  414.                 if (reverse_order)
  415.                     lptr -= xsize * sizeof(Py_UInt32);
  416.                 else
  417.                     lptr += xsize * sizeof(Py_UInt32);
  418.             }
  419.         }
  420.         if (zsize == 3) 
  421.             setalpha(base, xsize * ysize);
  422.         else if (zsize < 3) 
  423.             copybw((Py_Int32 *) base, xsize * ysize);
  424.     }
  425.     else {
  426.         rv = PyString_FromStringAndSize((char *) 0,
  427.                        (xsize*ysize+TAGLEN)*sizeof(Py_Int32));
  428.         if (rv == NULL)
  429.             goto finally;
  430.  
  431.         base = (unsigned char *) PyString_AsString(rv);
  432. #ifdef ADD_TAGS
  433.         addlongimgtag(base, xsize, ysize);
  434. #endif
  435.         verdat = (unsigned char *)malloc(xsize);
  436.         fseek(inf, 512, SEEK_SET);
  437.         for (z = 0; z < zsize; z++) {
  438.             lptr = base;
  439.             if (reverse_order)
  440.                 lptr += (ysize - 1) * xsize
  441.                         * sizeof(Py_UInt32);
  442.             for (y = 0; y < ysize; y++) {
  443.                 fread(verdat, xsize, 1, inf);
  444.                 interleaverow(lptr, verdat, 3-z, xsize);
  445.                 if (reverse_order)
  446.                     lptr -= xsize * sizeof(Py_UInt32);
  447.                 else
  448.                     lptr += xsize * sizeof(Py_UInt32);
  449.             }
  450.         }
  451.         if (zsize == 3)
  452.             setalpha(base, xsize * ysize);
  453.         else if (zsize < 3) 
  454.             copybw((Py_Int32 *) base, xsize * ysize);
  455.     }
  456.   finally:
  457.     free(starttab);
  458.     free(lengthtab);
  459.     free(rledat);
  460.     free(verdat);
  461.     fclose(inf);
  462.     return rv;
  463. }
  464.  
  465. /* static utility functions for longimagedata */
  466.  
  467. static void
  468. interleaverow(lptr, cptr, z, n)
  469.     unsigned char *lptr, *cptr;
  470.     int z, n;
  471. {
  472.     lptr += z;
  473.     while (n--) {
  474.         *lptr = *cptr++;
  475.         lptr += 4;
  476.     }
  477. }
  478.  
  479. static void
  480. copybw(lptr, n)
  481.     Py_Int32 *lptr;
  482.     int n;
  483. {
  484.     while (n >= 8) {
  485.         lptr[0] = 0xff000000 + (0x010101 * (lptr[0] & 0xff));
  486.         lptr[1] = 0xff000000 + (0x010101 * (lptr[1] & 0xff));
  487.         lptr[2] = 0xff000000 + (0x010101 * (lptr[2] & 0xff));
  488.         lptr[3] = 0xff000000 + (0x010101 * (lptr[3] & 0xff));
  489.         lptr[4] = 0xff000000 + (0x010101 * (lptr[4] & 0xff));
  490.         lptr[5] = 0xff000000 + (0x010101 * (lptr[5] & 0xff));
  491.         lptr[6] = 0xff000000 + (0x010101 * (lptr[6] & 0xff));
  492.         lptr[7] = 0xff000000 + (0x010101 * (lptr[7] & 0xff));
  493.         lptr += 8;
  494.         n -= 8;
  495.     }
  496.     while (n--) {
  497.         *lptr = 0xff000000 + (0x010101 * (*lptr&0xff));
  498.         lptr++;
  499.     }
  500. }
  501.  
  502. static void
  503. setalpha(lptr, n)
  504.     unsigned char *lptr;
  505. {
  506.     while (n >= 8) {
  507.         lptr[0 * 4] = 0xff;
  508.         lptr[1 * 4] = 0xff;
  509.         lptr[2 * 4] = 0xff;
  510.         lptr[3 * 4] = 0xff;
  511.         lptr[4 * 4] = 0xff;
  512.         lptr[5 * 4] = 0xff;
  513.         lptr[6 * 4] = 0xff;
  514.         lptr[7 * 4] = 0xff;
  515.         lptr += 4 * 8;
  516.         n -= 8;
  517.     }
  518.     while (n--) {
  519.         *lptr = 0xff;
  520.         lptr += 4;
  521.     }
  522. }
  523.  
  524. static void
  525. expandrow(optr, iptr, z)
  526.     unsigned char *optr, *iptr;
  527.     int z;
  528. {
  529.     unsigned char pixel, count;
  530.  
  531.     optr += z;
  532.     while (1) {
  533.         pixel = *iptr++;
  534.         if (!(count = (pixel & 0x7f)))
  535.             return;
  536.         if (pixel & 0x80) {
  537.             while (count >= 8) {
  538.                 optr[0 * 4] = iptr[0];
  539.                 optr[1 * 4] = iptr[1];
  540.                 optr[2 * 4] = iptr[2];
  541.                 optr[3 * 4] = iptr[3];
  542.                 optr[4 * 4] = iptr[4];
  543.                 optr[5 * 4] = iptr[5];
  544.                 optr[6 * 4] = iptr[6];
  545.                 optr[7 * 4] = iptr[7];
  546.                 optr += 8 * 4;
  547.                 iptr += 8;
  548.                 count -= 8;
  549.             }
  550.             while (count--) {
  551.                 *optr = *iptr++;
  552.                 optr += 4;
  553.             }
  554.         }
  555.         else {
  556.             pixel = *iptr++;
  557.             while (count >= 8) {
  558.                 optr[0 * 4] = pixel;
  559.                 optr[1 * 4] = pixel;
  560.                 optr[2 * 4] = pixel;
  561.                 optr[3 * 4] = pixel;
  562.                 optr[4 * 4] = pixel;
  563.                 optr[5 * 4] = pixel;
  564.                 optr[6 * 4] = pixel;
  565.                 optr[7 * 4] = pixel;
  566.                 optr += 8 * 4;
  567.                 count -= 8;
  568.             }
  569.             while (count--) {
  570.                 *optr = pixel;
  571.                 optr += 4;
  572.             }
  573.         }
  574.     }
  575. }
  576.  
  577. /*
  578.  *    longstoimage -
  579.  *        copy an array of longs to an iris image file.  Each long
  580.  *    represents one pixel.  xsize and ysize specify the dimensions of
  581.  *    the pixel array.  zsize specifies what kind of image file to
  582.  *    write out.  if zsize is 1, the luminance of the pixels are
  583.  *    calculated, and a sinlge channel black and white image is saved.
  584.  *    If zsize is 3, an RGB image file is saved.  If zsize is 4, an
  585.  *    RGBA image file is saved.
  586.  *
  587.  */
  588. static PyObject *
  589. longstoimage(self, args)
  590.     PyObject *self, *args;
  591. {
  592.     unsigned char *lptr;
  593.     char *name;
  594.     int xsize, ysize, zsize;
  595.     FILE *outf = NULL;
  596.     IMAGE image;
  597.     int tablen, y, z, pos, len;
  598.     Py_Int32 *starttab = NULL, *lengthtab = NULL;
  599.     unsigned char *rlebuf = NULL;
  600.     unsigned char *lumbuf = NULL;
  601.     int rlebuflen, goodwrite;
  602.     PyObject *retval = NULL;
  603.  
  604.     if (!PyArg_Parse(args, "(s#iiis)", &lptr, &len, &xsize, &ysize, &zsize,
  605.              &name))
  606.         return NULL;
  607.  
  608.     goodwrite = 1;
  609.     outf = fopen(name, "wb");
  610.     if (!outf) {
  611.         PyErr_SetString(ImgfileError, "can't open output file");
  612.         return NULL;
  613.     }
  614.     tablen = ysize * zsize * sizeof(Py_Int32);
  615.  
  616.     starttab = (Py_Int32 *)malloc(tablen);
  617.     lengthtab = (Py_Int32 *)malloc(tablen);
  618.     rlebuflen = (int) (1.05 * xsize + 10);
  619.     rlebuf = (unsigned char *)malloc(rlebuflen);
  620.     lumbuf = (unsigned char *)malloc(xsize * sizeof(Py_Int32));
  621.     if (!starttab || !lengthtab || !rlebuf || !lumbuf) {
  622.         PyErr_NoMemory();
  623.         goto finally;
  624.     }
  625.     
  626.     memset(&image, 0, sizeof(IMAGE));
  627.     image.imagic = IMAGIC; 
  628.     image.type = RLE(1);
  629.     if (zsize>1)
  630.         image.dim = 3;
  631.     else
  632.         image.dim = 2;
  633.     image.xsize = xsize;
  634.     image.ysize = ysize;
  635.     image.zsize = zsize;
  636.     image.min = 0;
  637.     image.max = 255;
  638.     goodwrite *= writeheader(outf, &image);
  639.     pos = 512 + 2 * tablen;
  640.     fseek(outf, pos, SEEK_SET);
  641.     if (reverse_order)
  642.         lptr += (ysize - 1) * xsize * sizeof(Py_UInt32);
  643.     for (y = 0; y < ysize; y++) {
  644.         for (z = 0; z < zsize; z++) {
  645.             if (zsize == 1) {
  646.                 lumrow(lptr, lumbuf, xsize);
  647.                 len = compressrow(lumbuf, rlebuf,
  648.                           CHANOFFSET(z), xsize);
  649.             } else {
  650.                 len = compressrow(lptr, rlebuf,
  651.                           CHANOFFSET(z), xsize);
  652.             }
  653.             if(len > rlebuflen) {
  654.                 PyErr_SetString(ImgfileError,
  655.                         "rlebuf is too small");
  656.                 goto finally;
  657.             }
  658.             goodwrite *= fwrite(rlebuf, len, 1, outf);
  659.             starttab[y + z * ysize] = pos;
  660.             lengthtab[y + z * ysize] = len;
  661.             pos += len;
  662.         }
  663.         if (reverse_order)
  664.             lptr -= xsize * sizeof(Py_UInt32);
  665.         else
  666.             lptr += xsize * sizeof(Py_UInt32);
  667.     }
  668.  
  669.     fseek(outf, 512, SEEK_SET);
  670.     goodwrite *= writetab(outf, starttab, ysize*zsize);
  671.     goodwrite *= writetab(outf, lengthtab, ysize*zsize);
  672.     if (goodwrite) {
  673.         Py_INCREF(Py_None);
  674.         retval = Py_None;
  675.     } else
  676.         PyErr_SetString(ImgfileError, "not enough space for image");
  677.  
  678.   finally:
  679.     fclose(outf);
  680.     free(starttab);
  681.     free(lengthtab);
  682.     free(rlebuf);
  683.     free(lumbuf);
  684.     return retval;
  685. }
  686.  
  687. /* static utility functions for longstoimage */
  688.  
  689. static void
  690. lumrow(rgbptr, lumptr, n)
  691.     unsigned char *rgbptr, *lumptr;
  692.     int n;
  693. {
  694.     lumptr += CHANOFFSET(0);
  695.     while (n--) {
  696.         *lumptr = ILUM(rgbptr[OFFSET_R],
  697.                    rgbptr[OFFSET_G],
  698.                    rgbptr[OFFSET_B]);
  699.         lumptr += 4;
  700.         rgbptr += 4;
  701.     }
  702. }
  703.  
  704. static int
  705. compressrow(lbuf, rlebuf, z, cnt)
  706.     unsigned char *lbuf, *rlebuf;
  707.     int z, cnt;
  708. {
  709.     unsigned char *iptr, *ibufend, *sptr, *optr;
  710.     short todo, cc;                            
  711.     Py_Int32 count;
  712.  
  713.     lbuf += z;
  714.     iptr = lbuf;
  715.     ibufend = iptr + cnt * 4;
  716.     optr = rlebuf;
  717.  
  718.     while(iptr < ibufend) {
  719.         sptr = iptr;
  720.         iptr += 8;
  721.         while ((iptr<ibufend) &&
  722.                ((iptr[-8]!=iptr[-4]) ||(iptr[-4]!=iptr[0])))
  723.         {
  724.             iptr += 4;
  725.         }
  726.         iptr -= 8;
  727.         count = (iptr - sptr) / 4;
  728.         while (count) {
  729.             todo = count > 126 ? 126 : (short)count;
  730.             count -= todo;
  731.             *optr++ = 0x80 | todo;
  732.             while (todo > 8) {
  733.                 optr[0] = sptr[0 * 4];
  734.                 optr[1] = sptr[1 * 4];
  735.                 optr[2] = sptr[2 * 4];
  736.                 optr[3] = sptr[3 * 4];
  737.                 optr[4] = sptr[4 * 4];
  738.                 optr[5] = sptr[5 * 4];
  739.                 optr[6] = sptr[6 * 4];
  740.                 optr[7] = sptr[7 * 4];
  741.                 optr += 8;
  742.                 sptr += 8 * 4;
  743.                 todo -= 8;
  744.             }
  745.             while (todo--) {
  746.                 *optr++ = *sptr;
  747.                 sptr += 4;
  748.             }
  749.         }
  750.         sptr = iptr;
  751.         cc = *iptr;
  752.         iptr += 4;
  753.         while ((iptr < ibufend) && (*iptr == cc))
  754.             iptr += 4;
  755.         count = (iptr - sptr) / 4;
  756.         while (count) {
  757.             todo = count > 126 ? 126 : (short)count;
  758.             count -= todo;
  759.             *optr++ = (unsigned char) todo;
  760.             *optr++ = (unsigned char) cc;
  761.         }
  762.     }
  763.     *optr++ = 0;
  764.     return optr - (unsigned char *)rlebuf;
  765. }
  766.  
  767. static PyObject *
  768. ttob(self, args)
  769.     PyObject *self;
  770.     PyObject *args;
  771. {
  772.     int order, oldorder;
  773.  
  774.     if (!PyArg_Parse(args, "i", &order))
  775.         return NULL;
  776.     oldorder = reverse_order;
  777.     reverse_order = order;
  778.     return PyInt_FromLong(oldorder);
  779. }
  780.  
  781. static PyMethodDef
  782. rgbimg_methods[] = {
  783.     {"sizeofimage",       sizeofimage},
  784.     {"longimagedata",  longimagedata},
  785.     {"longstoimage",   longstoimage},
  786.     {"ttob",       ttob},
  787.     {NULL,             NULL}         /* sentinel */
  788. };
  789.  
  790.  
  791. DL_EXPORT(void)
  792. initrgbimg()
  793. {
  794.     PyObject *m, *d;
  795.     m = Py_InitModule("rgbimg", rgbimg_methods);
  796.     d = PyModule_GetDict(m);
  797.     ImgfileError = PyErr_NewException("rgbimg.error", NULL, NULL);
  798.     if (ImgfileError != NULL)
  799.         PyDict_SetItemString(d, "error", ImgfileError);
  800. }
  801.