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 / wriff.c < prev    next >
C/C++ Source or Header  |  1991-10-19  |  13KB  |  628 lines

  1. /* wasp - copyright Steven Reiz 1990, 1991
  2.  * see wasp.c for further info
  3.  * wriff.c, 4/12/90 - 30/1/91,
  4.  * 5/5/91 - 2/6/91, 23/6/91, 30/6/91 - 8/7/91
  5.  */
  6.  
  7. #include "wasp.h"
  8. #define WRIFFMAIN
  9. #include "wriff.h"
  10. #ifndef NOSH
  11. #include "wriff.sh"
  12. #endif
  13.  
  14. static int ticolors;
  15.  
  16.  
  17. #ifdef __STDC__
  18. write_iff(void)
  19. #else
  20. write_iff()
  21. #endif
  22. {
  23.     long patchadr1, patchadr2;
  24.     long t;
  25.  
  26.     err=0; err2=0;
  27.     wriff_init();
  28.     decide_mode();
  29.     compute_nregs();
  30.     wrl(id('F', 'O', 'R', 'M'));
  31.     patchadr1=4;
  32.     wrl(0L); /* size of the form ilbm, will be patched later */
  33.     wrl(id('I', 'L', 'B', 'M'));
  34.     write_header();
  35.     write_cmap();
  36.     write_sham();
  37.     patchadr2=lseek(outfd, 0L, 1)+4; /* the size of the body chunk will be patched later */
  38.     write_body();
  39.     t=lseek(outfd, 0L, 1);
  40.     lseek(outfd, patchadr1, 0);
  41.     wrl(t-patchadr1-4);
  42.     lseek(outfd, patchadr2, 0);
  43.     wrl(t-patchadr2-4);
  44.     write_cmap();
  45.     write_sham();
  46.     printf("IFF file written; %ld bytes, error: %ld, error2: %ld\n", t, err, err2);
  47. }
  48.  
  49.  
  50. #ifdef __STDC__
  51. wriff_init(void)
  52. #else
  53. wriff_init()
  54. #endif
  55. {
  56.     slicedo=0;
  57.     counts=NULL1;
  58.     cm=NULL1;
  59.     curcm=NULL1;
  60.     wf2rgbweight=NULL1;
  61.     cmrgb=NULL1;
  62.     newcol=NULL1;
  63.     error=NULL1;
  64.     error2=NULL1;
  65. }
  66.  
  67.  
  68. #ifdef __STDC__
  69. decide_mode(void)
  70. #else
  71. decide_mode()
  72. #endif
  73. {
  74.     float sx, sy, st;
  75.  
  76.     if (directrgb>=0) {
  77.     if (directrgb%3)
  78.         error1(E0_FATAL, E1_IFF_RGB, E2_OPTION, E3_WRONG_NR_PLANES, (int)directrgb);
  79.     nplanes=directrgb;
  80.     printf("IFF output; direct rgb, %d planes\n", nplanes);
  81.     return;
  82.     }
  83.     if ((xmode!=UNSET || ymode!=UNSET) && asc)
  84.     error0(E0_FATAL, E1_IFF, E2_OPTION, E3_ASC);
  85.     if (xmode!=UNSET && hires!=HIRES_OK)
  86.     error0(E0_FATAL, E1_IFF, E2_OPTION, E3_NOHIRES);
  87.     count_pixels(0, (int)ysz-1, 1);
  88.     ticolors=icolors=count_colors(1L);
  89.     if (hires==HIRES_MAYBE)
  90.         hires=(icolors<=16 ? HIRES_OK : HIRES_NOT);
  91.     if (asc && (xsz>scrw || ysz>scrh)) {
  92.         sx=(float)scrw/(float)xsz;
  93.         sy=(float)scrh/(float)ysz;
  94.         if (sy<sx)
  95.             st=sy;
  96.         else
  97.             st=sx;
  98.         ymode=LACE;
  99.         sy=st*2.0;
  100.         if (hires==HIRES_OK) {
  101.             xmode=HIRES;
  102.             sx=st*2.0;
  103.         } else {
  104.             sx=st;
  105.             if (sy>1.0) {
  106.                 sx=sx/sy;
  107.                 sy=1.0;
  108.             }
  109.         }
  110.         if (sx!=sy || sx<1.0) {
  111.             scalef(1, sy);
  112.             scalef(0, sx);
  113.         }
  114.     }
  115.     if (xmode==UNSET) {
  116.         if (icolors<=32)
  117.             xmode=LORES;
  118.         else
  119.             xmode=HAM;
  120.     }
  121.     slicedo=sliced;
  122.     if (ymode==UNSET)
  123.         ymode=NOLACE;
  124.     if (distrmeth2!=DISTRMETH_UNSET && xmode!=HAM)
  125.     error0(E0_FATAL, E1_IFF, E2_OPTION, E3_ITMETH);
  126.     if (!inoperation && distrmeth==DISTRMETH_UNSET) {
  127.         if (xmode==EHB)
  128.             distrmeth=DEF_EHB_DISTRMETH;
  129.         else
  130.             distrmeth=DEF_DISTRMETH;
  131.     }
  132.     if (countmeth==COUNTMETH_UNSET)
  133.     countmeth=(xmode==HAM ? DEF_HAM_COUNTMETH : DEF_COUNTMETH);
  134.     if (xmode==EHB && !is_ehb_distr())
  135.     error1(E0_FATAL, E1_IFF, E2_OPTION, E3_EHB_METH, dmethnam(distrmeth));
  136.     printf("IFF output; xmode: %s%s, ymode: %s, cmeth: %s, dmeth: %s",
  137.      (slicedo ? "sliced " : ""), xmodenam(xmode), ymodenam(ymode),
  138.      cmethnam(countmeth), dmethnam(distrmeth));
  139.     if (distrmeth2!=DISTRMETH_UNSET)
  140.     printf(", dmeth2: %s", dmethnam(distrmeth2));
  141.     putchar('\n');
  142. }
  143.  
  144.  
  145. #ifdef __STDC__
  146. int is_ehb_distr(void)
  147. #else
  148. int is_ehb_distr()
  149. #endif
  150. {
  151.     return (distrmeth==DISTRMETH_EHB || distrmeth==DISTRMETH_MUE ? 1 : 0);
  152. }
  153.  
  154.  
  155. #ifdef __STDC__
  156. compute_nregs(void)
  157. #else
  158. compute_nregs()
  159. #endif
  160. {
  161.     if (directrgb>=0)
  162.     return;
  163.     switch (xmode) {
  164.     case HAM:   nregs=16; nplanes=6; break;
  165.     case EHB:   nregs=64; nplanes=6; break;
  166.     case LORES: nregs=32; nplanes=5; break;
  167.     case HIRES: nregs=16; nplanes=4; break;
  168.     }
  169.     if (slicedo) {
  170.         cm=Malloc((ymode==LACE && sliced==SLICED_SHAM ? (ysz+1)/2 : ysz)*nregs*sizeof(u_short));
  171.     curcm=cm;
  172.         goto compute_npixvals;
  173.     }
  174.     count_pixels(0, (int)ysz-1, 0);
  175.     icolors=count_colors(1L);
  176.     if (icolors>nregs && threshold>1) {
  177.         icolors=count_colors(threshold);
  178.         if (icolors<nregs) {
  179.             u_long mint, curt, maxt;
  180.  
  181.             printf("%d colors occur at least %ld times, trying to complete to %d\n",
  182.              icolors, threshold, nregs);
  183.             mint=1;
  184.             maxt=threshold;
  185.             while (maxt>mint+1) {
  186.                 curt=(mint+maxt)/2;
  187.                 icolors=count_colors(curt);
  188.                 if (icolors<nregs)
  189.                     maxt=curt-1;
  190.                 else
  191.                     mint=curt;
  192.             }
  193.             threshold=(mint+maxt)/2;
  194.             icolors=count_colors(threshold);
  195.             printf("%d colors occur at least %ld times\n", icolors, threshold);
  196.         }
  197.     }
  198.     if (xmode==LORES || xmode==HIRES) {
  199.         if (icolors<nregs)
  200.             nplanes=ceillog2((u_long)icolors);
  201.         else
  202.             nplanes=ceillog2((u_long)nregs);
  203.         nregs=1<<nplanes;
  204.     }
  205.     cm=Malloc(nregs*sizeof(u_short));
  206.     curcm=cm;
  207. compute_npixvals:
  208.     if (distrmeth2!=DISTRMETH_UNSET) {
  209.     cm0=Malloc(nregs*sizeof(u_short));
  210.     cmprev=Malloc(nregs*sizeof(u_short));
  211.     }
  212.     npixvals=1<<nplanes;
  213.     printf("%d colors", ticolors);
  214.     if (icolors!=ticolors)
  215.         printf(", counting %d colors", icolors);
  216.     printf(", %d color registers, %d planes", nregs, nplanes);
  217.     if (nregs-icolors>0)
  218.         printf(", %d color registers will be wasted", nregs-icolors);
  219.     printf("\n");
  220.     if (nregs<2 || xsz<2 || ysz<2)
  221.     error0(E0_FATAL, E1_IFF, E2_FORMAT, E3_2SIMPLE);
  222.     assert(nplanes>0 && nplanes<=MAXNPLANES);
  223.     assert(nregs<=MAXNREGS);
  224. }
  225.  
  226.  
  227. #ifdef __STDC__
  228. PRIVATE write_header(void)
  229. #else
  230. PRIVATE write_header()
  231. #endif
  232. {
  233.     struct bmhd_t {
  234.         u_short w, h;
  235.         short x, y;
  236.         u_char nplanes, masking, compression, pad;
  237.         u_short transpcol;
  238.         u_char xaspect, yaspect;
  239.         short pagew, pageh;
  240.     } bmhd;
  241.     u_long viewmodes;
  242.  
  243.     wrl(id('B', 'M', 'H', 'D'));
  244.     wrl((long)sizeof(bmhd));
  245.     bmhd.w=xsz;
  246.     bmhd.h=ysz;
  247.     bmhd.x=bmhd.y=0;
  248.     bmhd.nplanes=nplanes;
  249.     bmhd.masking=0;
  250.     bmhd.compression=compression;
  251.     bmhd.pad=0;
  252.     bmhd.transpcol=0;
  253.     bmhd.yaspect=11;
  254.     if (xmode==HIRES && ymode==NOLACE)
  255.         bmhd.xaspect=5;
  256.     else if (xmode!=HIRES && ymode==LACE)
  257.         bmhd.xaspect=20;
  258.     else
  259.         bmhd.xaspect=10;
  260.     bmhd.pagew=bmhd.w;
  261.     bmhd.pageh=bmhd.h;
  262.     cwrite(&bmhd, sizeof(bmhd));
  263.     if (directrgb>=0)
  264.     return;
  265.     wrl(id('C', 'A', 'M', 'G'));
  266.     wrl(4L);
  267.     viewmodes=0;
  268.     if (xmode==HIRES)
  269.         viewmodes|=VM_HIRES;
  270.     else if (xmode==HAM)
  271.         viewmodes|=VM_HAM;
  272.     else if (xmode==EHB)
  273.         viewmodes|=VM_EHB;
  274.     if (ymode==LACE)
  275.         viewmodes|=VM_LACE;
  276.     wrl(viewmodes);
  277. }
  278.  
  279.  
  280. #ifdef __STDC__
  281. PRIVATE write_cmap(void)
  282. #else
  283. PRIVATE write_cmap()
  284. #endif
  285. {
  286.     u_char *cmbuf;
  287.     long t;
  288.     short i, j, nr;
  289.     static long pos= -1;
  290.  
  291.     if (directrgb>=0)
  292.     return;
  293.     if (xmode==EHB)
  294.         nr=nregs/2;
  295.     else
  296.         nr=nregs;
  297.     t=nr*3;
  298.     if (pos== -1) {
  299.         wrl(id('C', 'M', 'A', 'P'));
  300.         wrl(t);
  301.         pos=lseek(outfd, 0L, 1);
  302.     } else
  303.         lseek(outfd, pos, 0);
  304.     cmbuf=Malloc(t);
  305.     for (i=0, j=0; i<nr; ++i) {
  306.         cmbuf[j++]=(cm[i]&0x0f00)>>4;
  307.         cmbuf[j++]= cm[i]&0x00f0;
  308.         cmbuf[j++]=(cm[i]&0x000f)<<4;
  309.     }
  310.     cwrite(cmbuf, (int)t);
  311.     free(cmbuf);
  312. }
  313.  
  314.  
  315. #ifdef __STDC__
  316. PRIVATE write_sham(void)
  317. #else
  318. PRIVATE write_sham()
  319. #endif
  320. {
  321.     long t;
  322.     static long pos= -1;
  323.     short version;
  324.  
  325.     if (!slicedo)
  326.     return;
  327.     if (xmode==EHB)
  328.     error0(E0_FATAL, E1_IFF, E2_EHB, E3_SLICED_EHB);
  329.     t=(ymode==LACE && sliced==SLICED_SHAM ? (ysz+1)/2 : ysz)*nregs*sizeof(u_short);
  330.     if (pos== -1) {
  331.     if (sliced==SLICED_SHAM) {
  332.             wrl(id('S', 'H', 'A', 'M'));
  333.             wrl(t+2);
  334.             version=0;
  335.             cwrite(&version, 2);
  336.     } else {
  337.             wrl(id('C', 'T', 'B', 'L'));
  338.             wrl(t);
  339.     }
  340.         pos=lseek(outfd, 0L, 1);
  341.     } else
  342.         lseek(outfd, pos, 0);
  343.     cwrite(cm, (int)t);
  344. }
  345.  
  346.  
  347. #ifdef __STDC__
  348. write_body(void)
  349. #else
  350. write_body()
  351. #endif
  352. {
  353.     int y, step;
  354. #ifdef __STDC__
  355.     int (*outfunc)(int);
  356. #else
  357.     int (*outfunc)();
  358. #endif
  359.  
  360.     if (directrgb<0)
  361.     fillconv();
  362.     if (xmode==HAM)
  363.     assert(nplanes==6);
  364.     if (!inoperation) {
  365.         wrl(id('B', 'O', 'D', 'Y'));
  366.         wrl(0L);
  367.     }
  368.     bytesperrow=(xsz+15)/16*2;
  369.     noutrows=MAXOUTBUFSZ/(bytesperrow*nplanes);
  370.     if (noutrows==0)
  371.         noutrows=1;
  372.     outbufsz=noutrows*bytesperrow*nplanes;
  373.     outrows=Malloc(outbufsz);
  374.     if (compression)
  375.     outcrows=Malloc(outbufsz*3/2);
  376.     body_size=0;
  377.     curcm=cm;
  378.     if (xmode==HAM) {
  379.     fill_prgbtab();
  380.         outfunc=ham_row_out;
  381.     } else
  382.         outfunc=row_out;
  383.     if (directrgb>=0) {
  384.     nzero=nplanes/3-4;
  385.     if (nzero<0)
  386.         nzero=0;
  387.     ncolor=nplanes/3;
  388.     if (ncolor>4)
  389.         ncolor=4;
  390.     init_counter(0, (int)ysz, 10, NULL);
  391.     for (y=0; y<ysz; ++y)
  392.         rgb_row_out(y);
  393.     } else if (slicedo) {
  394.         if (ymode==LACE && sliced==SLICED_SHAM)
  395.             step=2;
  396.         else
  397.             step=1;
  398.     init_counter(0, (int)ysz, 5, NULL);
  399.         for (y=0; y<ysz; y+=step) {
  400.             if (y==ysz-1)
  401.                 step=1;
  402.             count_pixels(y, y+step-1, 0);
  403.             icolors=count_colors(threshold);
  404.             if (icolors<nregs && threshold>1)
  405.                     printf("in row %d (and %d) only %d colors occur at least %ld times\n",
  406.                      y, y+step-1, icolors, threshold);
  407.             compute_distr(y, y+step-1);
  408.             outfunc(y);
  409.             if (step==2)
  410.                 outfunc(y+1);
  411.             curcm+=16;
  412.         }
  413.     } else {
  414.         compute_distr(0, (int)ysz-1);
  415.     init_counter(0, (int)ysz, 10, NULL);
  416.         for (y=0; y<ysz; ++y)
  417.             outfunc(y);
  418.     }
  419.     if (!inoperation)
  420.         (void)next_row(1); /* to flush the row buffer */
  421.     erase_counter(NULL);
  422. }
  423.  
  424.  
  425. #ifdef __STDC__
  426. PRIVATE fillconv(void)
  427. #else
  428. PRIVATE fillconv()
  429. #endif
  430. {
  431.     short i, j, k;
  432.     u_char *p;
  433.  
  434.     conv=Malloc(npixvals*8*MAXNPLANES);
  435.     p=conv;
  436.     for (i=0; i<npixvals; ++i) {
  437.         for (j=128; j; j>>=1) {
  438.             for (k=0; k<nplanes; ++k) {
  439.                 if (i&(1<<k))
  440.                     *p++ =j;
  441.                 else
  442.                     *p++ =0;
  443.             }
  444.             p+=MAXNPLANES-nplanes;
  445.         }
  446.     }
  447. }
  448.  
  449.  
  450. #ifdef __STDC__
  451. PRIVATE int cmpcolregs(short *p1, short *p2)
  452. #else
  453. PRIVATE int cmpcolregs(p1, p2)
  454. short *p1, *p2;
  455. #endif
  456. {
  457.     short c1, c2, i;
  458.  
  459.     c1= *p1;
  460.     c2= *p2;
  461.     i=((c1>>8) + ((c1&0x00f0)>>4) + (c1&0x000f))
  462.     - ((c2>>8) + ((c2&0x00f0)>>4) + (c2&0x000f));
  463.     if (i)
  464.         return (int)i;
  465.     i=(c1>>8)-(c2>>8);
  466.     if (i)
  467.         return (int)i;
  468.     i=((c1&0x00f0)>>4)-((c2&0x00f0)>>4);
  469.     if (i)
  470.         return (int)i;
  471.     i=(c1&0x000f)-(c2&0x000f);
  472.     return (int)i;
  473. }
  474.  
  475.  
  476. #ifdef __STDC__
  477. sort_cm(void)
  478. #else
  479. sort_cm()
  480. #endif
  481. {
  482.     qsort((char *)curcm, (int)nregs, sizeof(u_short), cmpcolregs);
  483. }
  484.  
  485.  
  486. static char *qm="?";
  487.  
  488.  
  489. static char *sliceds[]={
  490.     "ok",
  491.     "not",
  492.     "maybe",
  493.     NULL
  494. };
  495. #ifdef __STDC__
  496. char *slicednam(int i)
  497. #else
  498. char *slicednam(i)
  499. int i;
  500. #endif
  501. {
  502.     if (i<0 || i>2)
  503.         return qm;
  504.     return sliceds[i];
  505. }
  506.  
  507.  
  508. static char *xmodes[]={
  509.     "unset",
  510.     "hires",
  511.     "lores",
  512.     "ehb",
  513.     "ham",
  514.     NULL
  515. };
  516. #ifdef __STDC__
  517. char *xmodenam(int i)
  518. #else
  519. char *xmodenam(i)
  520. int i;
  521. #endif
  522. {
  523.     if (i<0 || i>4)
  524.         return qm;
  525.     return xmodes[i];
  526. }
  527.  
  528.  
  529. static char *ymodes[]={
  530.     "unset",
  531.     "lace",
  532.     "nolace",
  533.     NULL
  534. };
  535. #ifdef __STDC__
  536. char *ymodenam(int i)
  537. #else
  538. char *ymodenam(i)
  539. int i;
  540. #endif
  541. {
  542.     if (i<0 || i>2)
  543.         return qm;
  544.     return ymodes[i];
  545. }
  546.  
  547.  
  548. /* should be in same order as DISTRMETH_ defines in wasp.h */
  549. static char *dmeths[]={
  550.     "unset",
  551.     "mu",
  552.     "wf",
  553.     "ehb",
  554.     "mue",
  555.     "hs",
  556.     "con",
  557.     NULL
  558. };
  559. #ifdef __STDC__
  560. char *dmethnam(int i)
  561. #else
  562. char *dmethnam(i)
  563. int i;
  564. #endif
  565. {
  566.     if (i<0 || i>6)
  567.         return qm;
  568.     return dmeths[i];
  569. }
  570. #ifdef __STDC__
  571. int dmethnum(char *s)
  572. #else
  573. int dmethnum(s)
  574. char *s;
  575. #endif
  576. {
  577.     int i;
  578.  
  579.     for (i=1; dmeths[i]; ++i)
  580.         if (!strcmp(s, dmeths[i]))
  581.             return i;
  582.     return -1;
  583. }
  584.  
  585.  
  586. /* should be in same order as COUNTMETH_ defines in wasp.h */
  587. static char *cmeths[]={
  588.     "unset",
  589.     "all1",
  590.     "alldif",
  591.     "allfdif",
  592.     "j1",
  593.     "j21",
  594.     "jdif",
  595.     "jdifsh",
  596.     "jfdif",
  597.     "jfdifsh",
  598.     "hmgs",
  599.     "hmcubic",
  600.     "hm",
  601.     NULL
  602. };
  603. #ifdef __STDC__
  604. char *cmethnam(int i)
  605. #else
  606. char *cmethnam(i)
  607. int i;
  608. #endif
  609. {
  610.     if (i<0 || i>12)
  611.         return qm;
  612.     return cmeths[i];
  613. }
  614. #ifdef __STDC__
  615. int cmethnum(char *s)
  616. #else
  617. int cmethnum(s)
  618. char *s;
  619. #endif
  620. {
  621.     int i;
  622.  
  623.     for (i=1; cmeths[i]; ++i)
  624.         if (!strcmp(s, cmeths[i]))
  625.             return i;
  626.     return -1;
  627. }
  628.