home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 564a.lha / wasp_v1.21 / Src.LZH / Src / readiff.c < prev    next >
C/C++ Source or Header  |  1991-10-19  |  16KB  |  712 lines

  1. /* wasp - copyright Steven Reiz 1990, 1991
  2.  * see wasp.c for further info
  3.  * readiff.c, 4/12/90 - 31/12/90,
  4.  * 5/5/91 - 2/6/91, 23/6/91, 9/7/91
  5.  */
  6.  
  7. #include "wasp.h"
  8. #ifndef NOSH
  9. #include "readiff.sh"
  10. #endif
  11.  
  12. static u_long pos;
  13. static short seen_bmhd, seen_cmap, seen_sham, seen_camg, seen_body;
  14. static short laced_sham=0; /* one sham entry per two lines in lace mode */
  15. static u_long viewmodes=0;
  16. static struct bmhd_t {
  17.     u_short w, h;
  18.     short x, y;
  19.     u_char nplanes, masking, compression, pad;
  20.     u_short transpcol;
  21.     u_char xaspect, yaspect;
  22.     short pagew, pageh;
  23. } bmhd;
  24. static u_short *cmap, *curcmap;
  25. static u_short *sham=NULL;
  26. static short nplanes, ncmap, nregs, nsham, directrrgb=0;
  27.  
  28.  
  29. #ifdef __STDC__
  30. read_iff(void)
  31. #else
  32. read_iff()
  33. #endif
  34. {
  35.     u_long id;
  36.  
  37.     cread(&id, sizeof(id));
  38.     if (!isgroupid(id)) {
  39.         lseek(infd, 0L, 0);
  40.         return 0;
  41.     }
  42.     pos=sizeof(id);
  43.     seen_bmhd=seen_cmap=seen_sham=seen_camg=seen_body=0;
  44.     do_chunk(id);
  45.     if (!seen_bmhd)
  46.     error0(E0_FATAL, E1_IFF, E2_BMHD, E3_MISS_CHUNK);
  47.     if (!seen_body) {
  48.         if (!seen_camg) {
  49.         error0(E0_WARNING, E1_IFF, E2_CAMG, E3_MISS_CHUNK);
  50.             viewmodes=(nplanes==6 ? VM_HAM : 0);
  51.             seen_camg=1;
  52.         }
  53.         pos=sizeof(id);
  54.         lseek(infd, pos, 0);
  55.         do_chunk(id);
  56.     }
  57.     if (!seen_body)
  58.     error0(E0_FATAL, E1_IFF, E2_BODY, E3_MISS_CHUNK);
  59.     free(cmap);
  60.     return 1;
  61. }
  62.  
  63.  
  64. #ifdef __STDC__
  65. PRIVATE char *idstr(u_long id)
  66. #else
  67. PRIVATE char *idstr(id)
  68. u_long id;
  69. #endif
  70. {
  71.     static char ids[5];
  72.  
  73.     *(u_long *)ids=id;
  74.     ids[4]='\0';
  75.     return ids;
  76. }
  77.  
  78.  
  79. #ifdef __STDC__
  80. PRIVATE do_chunk(u_long id)
  81. #else
  82. PRIVATE do_chunk(id)
  83. u_long id;
  84. #endif
  85. {
  86.     u_long size, t, newpos;
  87.  
  88.     cread(&size, sizeof(size));
  89.     size=(size+1) & -2;
  90.     pos+=sizeof(size);
  91.     if (isgroupid(id)) {
  92.         cread(&t, sizeof(t));
  93.         pos+=sizeof(t);
  94.         if (size<0)
  95.         error0(E0_FATAL, E1_IFF, E2_FORMAT, E3_NEGGROUPSIZE);
  96.         newpos=pos+size-sizeof(t);
  97.         while (pos<newpos) {
  98.             u_long pid;
  99.     
  100.             cread(&pid, sizeof(pid));
  101.             pos+=sizeof(pid);
  102.             if (!isvalid(pid))
  103.         error0(E0_FATAL, E1_IFF, E2_FORMAT, E3_INVALID_ID);
  104.             else
  105.                 do_chunk(pid);
  106.         }
  107.         if (pos>newpos)
  108.         error0(E0_FATAL, E1_IFF, E2_FORMAT, E3_GROUP2SMALL);
  109.     } else {
  110.         /* normal chunks */
  111.         if (id==id('B', 'M', 'H', 'D') && !seen_bmhd) {
  112.             seen_bmhd=1;
  113.             if (size!=sizeof(struct bmhd_t))
  114.         error0(E0_FATAL, E1_IFF, E2_BMHD, E3_WRONGCHUNKSZ);
  115.             cread(&bmhd, (int)size);
  116.         nplanes=bmhd.nplanes;
  117.             pos+=size;
  118.         } else if (id==id('C', 'A', 'M', 'G') && !seen_camg) {
  119.         int nrmodes;
  120.  
  121.             seen_camg=1;
  122.             if (size!=sizeof(viewmodes))
  123.         error0(E0_FATAL, E1_IFF, E2_CAMG, E3_WRONGCHUNKSZ);
  124.             cread(&viewmodes, (int)size);
  125.         nrmodes=0;
  126.         if (viewmodes & VM_EHB)
  127.         ++nrmodes;
  128.         if (viewmodes & VM_HAM)
  129.         ++nrmodes;
  130.         if (viewmodes & VM_HIRES)
  131.         ++nrmodes;
  132.         if (nrmodes>1)
  133.         error0(E0_FATAL, E1_IFF, E2_CAMG, E3_CAMGMODES);
  134.             pos+=size;
  135.         } else if (id==id('C', 'M', 'A', 'P') && !seen_cmap) {
  136.             seen_cmap=1;
  137.             do_cmap(size);
  138.         } else if (id==id('S', 'H', 'A', 'M') && !seen_sham) {
  139.             seen_sham=1;
  140.             do_sham(size, 0);
  141.         } else if (id==id('C', 'T', 'B', 'L') && !seen_sham) {
  142.             seen_sham=1;
  143.             do_sham(size, 1);
  144.         } else if (id==id('B', 'O', 'D', 'Y') 
  145.          && !seen_body && seen_bmhd) {
  146.             seen_body=1;
  147.             do_body(size);
  148.     } else if (id==id('A', 'N', 'N', 'O')) {
  149.         do_anno(size);
  150.         } else { /* skip unknown chunks */
  151.         error2(E0_WARNING, E1_IFF, E2_FORMAT, E3_UNKNOWN_CHUNK, idstr(id), size);
  152.             lseek(infd, size, 1);
  153.             pos+=size;
  154.         }
  155.     }
  156. }
  157.  
  158.  
  159. #ifdef __STDC__
  160. PRIVATE int isgroupid(u_long id)
  161. #else
  162. PRIVATE int isgroupid(id)
  163. u_long id;
  164. #endif
  165. {
  166.     return isgroupid2(id, id('F', 'O', 'R', 'M')) ||
  167.            isgroupid2(id, id('L', 'I', 'S', 'T')) ||
  168.            isgroupid2(id, id('C', 'A', 'T', ' ')) ||
  169.            id==id('P', 'R', 'O', 'P');
  170. }
  171.  
  172.  
  173. #ifdef __STDC__
  174. PRIVATE int isgroupid2(u_long i, u_long i2)
  175. #else
  176. PRIVATE int isgroupid2(i, i2)
  177. u_long i, i2;
  178. #endif
  179. {
  180.     char c;
  181.  
  182.     c=i;
  183.     return i==i2 || ((i&0xffffff00L)==(i2&0xffffff00L) && c>='1' && c<='9');
  184. }
  185.  
  186.  
  187. #ifdef __STDC__
  188. PRIVATE int isvalid(u_long id)
  189. #else
  190. PRIVATE int isvalid(id)
  191. u_long id;
  192. #endif
  193. {
  194.     char *p;
  195.     int i;
  196.  
  197.     for (p=(char *)&id, i=0; i<4; ++i)
  198.         if (*p<' ' || *p>'~')
  199.             break;
  200.         else
  201.             ++p;
  202.     return i>=4;
  203. }
  204.  
  205.  
  206. #ifdef __STDC__
  207. PRIVATE do_anno(u_long size)
  208. #else
  209. PRIVATE do_anno(size)
  210. u_long size;
  211. #endif
  212. {
  213.     short i;
  214.     char *anno;
  215.  
  216.     anno=Malloc(size+1);
  217.     cread(anno, size);
  218.     anno[size]='\0';
  219.     for (i=0; i<size; ++i) {
  220.         if (i==size-1 && !anno[i])
  221.             break;
  222.         if (anno[i]<' ' || anno[i]>'~')
  223.             anno[i]='.';
  224.     }
  225.     printe("ANNO: %s\n", anno);
  226.     free(anno);
  227.     pos+=size;
  228. }
  229.  
  230.  
  231. #ifdef __STDC__
  232. PRIVATE do_cmap(u_long size)
  233. #else
  234. PRIVATE do_cmap(size)
  235. u_long size;
  236. #endif
  237. {
  238.     u_char filergb[3];
  239.     short i;
  240.  
  241.     if (size%6)
  242.     error0(E0_FATAL, E1_IFF, E2_CMAP, E3_WRONGCHUNKSZ);
  243.     ncmap=size/sizeof(filergb);
  244.     cmap=Malloc(ncmap*sizeof(u_short));
  245.     for (i=0; i<ncmap; ++i) {
  246.         cread(filergb, sizeof(filergb));
  247.         cmap[i]=((u_short)filergb[0]&0xf0)<<4 | filergb[1]&0xf0 | (u_long)filergb[2]>>4;
  248.     }
  249.     pos+=size;
  250. }
  251.  
  252.  
  253. #ifdef __STDC__
  254. PRIVATE extend_cmap(void)
  255. #else
  256. PRIVATE extend_cmap()
  257. #endif
  258. {
  259.     u_short *newcmap, rgb;
  260.     u_char r, g, b;
  261.     short i;
  262.  
  263.     newcmap=Malloc(2*ncmap*sizeof(u_short));
  264.     for (i=0; i<ncmap; ++i) {
  265.         rgb=cmap[i];
  266.         newcmap[i]=rgb;
  267.         r=(rgb&0x0f00)>>9;
  268.         g=(rgb&0x00f0)>>5;
  269.         b=(rgb&0x000f)>>1;
  270.         newcmap[i+ncmap]=(r<<8)|(g<<4)|b;
  271.     }
  272.     free(cmap);
  273.     cmap=newcmap;
  274.     ncmap*=2;
  275. }
  276.  
  277.  
  278. #ifdef __STDC__
  279. PRIVATE do_sham(u_long size, int is_ctbl)
  280. #else
  281. PRIVATE do_sham(size, is_ctbl)
  282. u_long size;
  283. int is_ctbl;
  284. #endif
  285. {
  286.     short i;
  287.  
  288.     pos+=size;
  289.     if (!is_ctbl) {
  290.         cread(&i, 2);
  291.         if (i)
  292.             error1(E0_WARNING, E1_IFF, E2_SHAM, E3_UNKNOWN_VERSION, (int)i);
  293.         size-=2;
  294.     }
  295.     sham=Malloc(size);
  296.     cread(sham, (int)size);
  297.     nsham=size/2;
  298.     for (i=0; i<nsham; ++i)
  299.         sham[i]&=0x0fff;
  300. }
  301.  
  302.  
  303. #ifdef __STDC__
  304. PRIVATE do_body(u_long size)
  305. #else
  306. PRIVATE do_body(size)
  307. u_long size;
  308. #endif
  309. {
  310.     short y;
  311.  
  312.     xsz=bmhd.w;
  313.     ysz=bmhd.h;
  314.     nregs=1<<nplanes;
  315.     if (viewmodes & VM_HAM)
  316.     nregs=16;
  317.     if (bmhd.masking)
  318.     error0(E0_FATAL, E1_IFF, E2_FORMAT, E3_MASKING);
  319.     if (bmhd.compression!=0 && bmhd.compression!=1)
  320.     error1(E0_FATAL, E1_IFF, E2_COMPRESSION, E3_UNKNOWN_VERSION, (int)bmhd.compression);
  321.     if (viewmodes & VM_HAM) {
  322.         if (ncmap!=nregs)
  323.         error1(E0_WARNING, E1_IFF, E2_HAM, E3_WRONG_NR_CREGS, (int)ncmap);
  324.     if (nplanes!=6)
  325.         error1(E0_FATAL, E1_IFF, E2_HAM, E3_WRONG_NR_PLANES, (int)nplanes);
  326.     } else if (viewmodes & VM_EHB) {
  327.     if (nplanes!=6)
  328.         error1(E0_FATAL, E1_IFF, E2_EHB, E3_WRONG_NR_PLANES, (int)nplanes);
  329.         extend_cmap();
  330.     } else if (!seen_cmap) {
  331.     directrrgb=1;
  332.     if (seen_camg)
  333.         error0(E0_FATAL, E1_IFF_RGB, E2_CAMG, E3_UNEXP_CHUNK);
  334.     if (sham)
  335.         error0(E0_FATAL, E1_IFF_RGB, E2_SHAM, E3_UNEXP_CHUNK);
  336.     if (nplanes<12 || nplanes%3)
  337.         error1(E0_FATAL, E1_IFF_RGB, E2_FORMAT, E3_WRONG_NR_PLANES, (int)nplanes);
  338.     } else {
  339.         if (ncmap!=(1<<nplanes))
  340.         error2(E0_FATAL, E1_IFF, E2_FORMAT, E3_CREGS_PLANES, (int)ncmap,
  341.          (int)nplanes);
  342.     }
  343.     if (sham) {
  344.         int i;
  345.  
  346.         if (viewmodes & VM_EHB)
  347.         error0(E0_FATAL, E1_IFF, E2_EHB, E3_SLICED_EHB);
  348.     i=ysz;
  349.         if ((viewmodes & VM_LACE) && nregs*i!=nsham) {
  350.             i=(ysz+1)/2;
  351.         laced_sham=1;
  352.     }
  353.         if (nregs*i!=nsham)
  354.         error2(E0_FATAL, E1_IFF, E2_SHAM, E3_NENTRIES, (int)nsham, nregs*i);
  355.     }
  356.     printf("IFF input; %ld x %ld, %d plane%s, ", xsz, ysz, (int)nplanes,
  357.      (nplanes==1 ? "" : "s"));
  358.     if (viewmodes & VM_LACE)
  359.     printf("interlaced ");
  360.     if (sham)
  361.     printf("%ssliced ", (laced_sham ? "lace-" : ""));
  362.     if (directrrgb)
  363.     printf("direct rgb\n");
  364.     else if (viewmodes & VM_EHB)
  365.     printf("ehb\n");
  366.     else if (viewmodes & VM_HAM)
  367.     printf("ham\n");
  368.     else if (viewmodes & VM_HIRES)
  369.     printf("hires\n");
  370.     else
  371.     printf("lores\n");
  372.     fflush(stdout);
  373.     if (!outfilename)
  374.     exit(0);
  375.     rgb=Malloc(ysz*sizeof(u_short *));
  376.     for (y=0; y<ysz; ++y)
  377.         rgb[y]=Malloc(xsz*sizeof(u_short));
  378.     set_bodylimit(size);
  379.     if (directrrgb)
  380.     read_direct_body();
  381.     else
  382.     read_body();
  383.     check_bodylimit();
  384.     pos+=size;
  385.     erase_counter(NULL);
  386. }
  387.  
  388.  
  389. static u_long bodylimit, bodypos;
  390. #define RBBUFSZ 32760
  391. static u_char *conv;
  392.  
  393. #ifdef __STDC__
  394. PRIVATE set_bodylimit(u_long size)
  395. #else
  396. PRIVATE set_bodylimit(size)
  397. u_long size;
  398. #endif
  399. {
  400.     bodylimit=size;
  401.     bodypos=0;
  402. }
  403.  
  404.  
  405. #ifdef __STDC__
  406. PRIVATE check_bodylimit(void)
  407. #else
  408. PRIVATE check_bodylimit()
  409. #endif
  410. {
  411.     if (bodypos!=bodylimit)
  412.     error0(E0_FATAL, E1_IFF, E2_BODY, E3_UNSPEC);
  413. }
  414.  
  415.  
  416. #ifdef __STDC__
  417. PRIVATE short nextbody(void *buf)
  418. #else
  419. PRIVATE short nextbody(buf)
  420. void *buf;
  421. #endif
  422. {
  423.     int toread;
  424.  
  425.     toread=bodylimit-bodypos;
  426.     if (toread<=0)
  427.     error0(E0_FATAL, E1_IFF, E2_BODY, E3_UNEXPEND);
  428.     if (toread>RBBUFSZ)
  429.         toread=RBBUFSZ;
  430.     cread(buf, toread);
  431.     bodypos+=toread;
  432.     return (short)toread;
  433. }
  434.  
  435.  
  436. #define nextc() (bufi<bufsz ? buf[bufi++] : ((bufsz=nextbody(buf)), (bufi=1), buf[0]))
  437.  
  438.  
  439. #ifdef __STDC__
  440. PRIVATE read_direct_body(void)
  441. #else
  442. PRIVATE read_direct_body()
  443. #endif
  444. {
  445.     short bufi, bufsz, x, y, z, planei;
  446.     u_char *buf;
  447.     char *row, *q, c;
  448.  
  449.     init_counter(0, (int)ysz, 10, NULL);
  450.     row=Malloc(nplanes*((xsz+7)/8));
  451.     buf=Malloc(RBBUFSZ);
  452.     bufi=bufsz=0;
  453.     for (y=0; y<ysz; ++y) {
  454.         counter();
  455.         for (planei=0; planei<nplanes; ++planei) {
  456.             if (bmhd.compression) {
  457.                 x=(xsz+7)/8;
  458.                 q=row+planei*x;
  459.                 while (x>0) {
  460.                     z=nextc();
  461.                     if (z<=127 && (x-=z, --x, x>=0)) {
  462.                         while (z>=0) {
  463.                 *q++ =nextc();
  464.                             --z;
  465.                         }
  466.                     } else if (z==128) {
  467.                         /* do nothing */
  468.                     } else if (z<=255 && (z=257-z, x-=z, x>=0)) {
  469.                         c=nextc();
  470.                         while (--z>=0)
  471.                             *q++ =c;
  472.                     }
  473.                 }
  474.                 if (x!=0)
  475.             error0(E0_FATAL, E1_IFF, E2_COMPRESSION, E3_ROWBOUND);
  476.             } else {
  477.                 if (bufi&1) {
  478.                     nextc();
  479.                 }
  480.                 for (x=(xsz+7)/8-1, q=row+planei*((xsz+7)/8); x>=0; --x)
  481.             *q++ =nextc();
  482.             }
  483.         }
  484.     do_row_direct(y, (u_char *)row);
  485.     }
  486.     if (bufi&1)
  487.         nextc();
  488.     free(row);
  489.     free(buf);
  490. }
  491.  
  492.  
  493. #ifdef __STDC__
  494. PRIVATE read_body(void)
  495. #else
  496. PRIVATE read_body()
  497. #endif
  498. {
  499.     short bufi, bufsz, x, y;
  500.     long lon;
  501.     short z;
  502.     u_char *buf;
  503.     u_long *p, *q, *row;
  504.  
  505.     init_counter(0, (int)ysz, 20, NULL);
  506.     if (sham)
  507.         curcmap=sham;
  508.     else
  509.         curcmap=cmap;
  510.     row=Malloc((xsz+7)/8*8);
  511.     buf=Malloc(RBBUFSZ);
  512.     bufi=bufsz=0;
  513.     conv=Malloc(nplanes*256*8);
  514.     fill_conv();
  515.     for (y=0; y<ysz; ++y) {
  516.         counter();
  517.         for (lon=(long)conv; lon<(long)conv+nplanes*256*8; lon+=256*8) {
  518.             if (bmhd.compression) {
  519.                 x=(xsz+7)/8;
  520.                 q=row;
  521.                 while (x>0) {
  522.                     z=nextc();
  523.                     if (z<=127 && (x-=z, --x, x>=0)) {
  524.                         while (z>=0) {
  525.                             p=(u_long *)(lon+(nextc()<<3));
  526.                             if (lon==(long)conv) {
  527.                                 *q++ = *p++;
  528.                                 *q++ = *p;
  529.                             } else {
  530.                                 *q++ |= *p++;
  531.                                 *q++ |= *p;
  532.                             }
  533.                             --z;
  534.                         }
  535.                     } else if (z==128) {
  536.                         /* do nothing */
  537.                     } else if (z<=255 && (z=257-z, x-=z, x>=0)) {
  538.                         p=(u_long *)(lon+(nextc()<<3));
  539.                         if (lon==(long)conv) {
  540.                             while (--z>=0) {
  541.                                 *q++ = *p++;
  542.                                 *q++ = *p;
  543.                                 --p;
  544.                             }
  545.                         } else {
  546.                             while (--z>=0) {
  547.                                 *q++ |= *p++;
  548.                                 *q++ |= *p;
  549.                                 --p;
  550.                             }
  551.                         }
  552.                     }
  553.                 }
  554.                 if (x!=0)
  555.             error0(E0_FATAL, E1_IFF, E2_COMPRESSION, E3_ROWBOUND);
  556.             } else {
  557.                 if (bufi&1)
  558.                     nextc();
  559.                 for (x=(xsz+7)/8-1, q=row; x>=0; --x) {
  560.                     p=(u_long *)(lon+(nextc()<<3));
  561.                     if (lon==(long)conv) {
  562.                         *q++ = *p++;
  563.                         *q++ = *p;
  564.                     } else {
  565.                         *q++ |= *p++;
  566.                         *q++ |= *p;
  567.                     }
  568.                 }
  569.             }
  570.         }
  571.         if (viewmodes & VM_HAM)
  572.             do_row_ham(y, (u_char *)row);
  573.         else
  574.             do_row(y, (u_char *)row);
  575.         if (sham && (!laced_sham || !(y&1)))
  576.             curcmap+=nregs;
  577.     }
  578.     if (bufi&1)
  579.         nextc();
  580.     free(conv);
  581.     free(row);
  582.     free(buf);
  583. }
  584.  
  585.  
  586. #ifdef __STDC__
  587. PRIVATE fill_conv(void)
  588. #else
  589. PRIVATE fill_conv()
  590. #endif
  591. {
  592.     u_char *powtab, *p;
  593.     short x, y;
  594.     char i;
  595.     short j;
  596.  
  597.     powtab=Malloc(8);
  598.     p=powtab;
  599.     for (i=1; i; i<<=1)
  600.         *p++ =i;
  601.     p=conv;
  602.     for (y=0; y<nplanes; ++y) {
  603.         for (x=0; x<256; ++x) {
  604.             for (j=128; j; j>>=1) {
  605.                 if (j&x)
  606.                     *p++ =powtab[y];
  607.                 else
  608.                     *p++ =0;
  609.             }
  610.         }
  611.     }
  612.     free(powtab);
  613. }
  614.  
  615.  
  616. #ifdef __STDC__
  617. PRIVATE do_row(short y, u_char *parrow)
  618. #else
  619. PRIVATE do_row(y, parrow)
  620. short y;
  621. u_char *parrow;
  622. #endif
  623. {
  624.     u_short *rgbrow;
  625.     u_char *row;
  626.     short x;
  627.  
  628.     rgbrow=rgb[y];
  629.     row=parrow;
  630.     for (x=xsz-1; x>=0; --x)
  631.         *rgbrow++ =curcmap[*row++];
  632. }
  633.  
  634.  
  635. #ifdef __STDC__
  636. PRIVATE do_row_ham(short y, u_char *parrow)
  637. #else
  638. PRIVATE do_row_ham(y, parrow)
  639. short y;
  640. u_char *parrow;
  641. #endif
  642. {
  643.     u_short *rgbrow;
  644.     u_char *row, pixel;
  645.     short x;
  646.     u_short curcolor;
  647.  
  648.     rgbrow=rgb[y];
  649.     row=parrow;
  650.     curcolor=curcmap[0];
  651.     x=xsz-1;
  652.     do {
  653.         pixel= *row++;
  654.         if (pixel&0x20) {
  655.             if (pixel&0x10) { /* modify green */
  656.                 curcolor=(curcolor&0x0f0f)|((pixel&0x0f)<<4);
  657.             } else {          /* modify red */
  658.                 curcolor=(curcolor&0x00ff)|((pixel&0x0f)<<8);
  659.             }
  660.         } else {
  661.             if (pixel&0x10) { /* modify blue */
  662.                 curcolor=(curcolor&0x0ff0)|(pixel&0x0f);
  663.             } else {          /* use curcmap */
  664.                 curcolor=curcmap[pixel];
  665.             }
  666.         }
  667.         *rgbrow++ =curcolor;
  668.     } while (--x>=0);
  669. }
  670.  
  671.  
  672. #ifdef __STDC__
  673. PRIVATE do_row_direct(short y, u_char *inrow)
  674. #else
  675. PRIVATE do_row_direct(y, inrow)
  676. short y;
  677. u_char *inrow;
  678. #endif
  679. {
  680.     u_short color, *dest;
  681.     long x, bytesperscan, plane0;
  682.     u_char *p, pmask, *plane1, *plane2, *plane3;
  683.  
  684.     dest=rgb[y];
  685.     bytesperscan=(xsz+7)/8;
  686.     plane0=nplanes/3*bytesperscan;
  687.     for (x=0; x<bytesperscan; ++x) {
  688.         plane1=inrow+x+plane0-bytesperscan;
  689.         plane2=plane1+plane0;
  690.         plane3=plane2+plane0;
  691.         for (pmask=128; pmask; pmask=(unsigned long)pmask>>1) {
  692.             color=0;
  693.             p=plane1;
  694.             if (*p & pmask)    color|=0x0800; p-=bytesperscan;
  695.             if (*p & pmask)    color|=0x0400; p-=bytesperscan;
  696.             if (*p & pmask)    color|=0x0200; p-=bytesperscan;
  697.             if (*p & pmask)    color|=0x0100;
  698.             p=plane2;
  699.             if (*p & pmask)    color|=0x0080; p-=bytesperscan;
  700.             if (*p & pmask)    color|=0x0040; p-=bytesperscan;
  701.             if (*p & pmask)    color|=0x0020; p-=bytesperscan;
  702.             if (*p & pmask)    color|=0x0010;
  703.             p=plane3;
  704.             if (*p & pmask)    color|=0x0008; p-=bytesperscan;
  705.             if (*p & pmask)    color|=0x0004; p-=bytesperscan;
  706.             if (*p & pmask)    color|=0x0002; p-=bytesperscan;
  707.             if (*p & pmask)    color|=0x0001;
  708.             *dest++ =color;
  709.         }
  710.     }
  711. }
  712.