home *** CD-ROM | disk | FTP | other *** search
- /* wasp - Copyright 1991 by Steven Reiz
- * see COPYING and wasp.c for further info
- * wriff.c, 4/12/90 - 30/1/91,
- * 5/5/91 - 2/6/91, 23/6/91, 30/6/91 - 8/7/91, 16/11/91,
- * 8/12/91, 31/12/91 - 1/1/92
- */
-
- static char *sourcefile=__FILE__;
-
- #include "wasp.h"
- #define WRIFFMAIN
- #include "wriff.h"
-
- static int ticolors;
- static int mmap_size_known=1;
-
-
- void
- write_iff(void)
- {
- long t;
-
- err=0; err2=0;
- wriff_init();
- decide_mode();
- compute_nregs();
- wrl(id('F', 'O', 'R', 'M'));
- wrl(0L); /* size of the form ilbm, will be patched later */
- wrl(id('I', 'L', 'B', 'M'));
- write_header();
- write_cmap();
- write_mmap();
- write_body();
- write_cmap();
- write_mmap();
- write_body();
- t=cseek_out(0L, 2);
- cseek_out(4L, 0);
- wrl(t-8L);
- printe("IFF file written; %ld bytes, error: %ld, error2: %ld\n", t, err, err2);
- }
-
-
- void
- wriff_init(void)
- {
- slicedo=0;
- counts=NULL1;
- cm=NULL1;
- curcm=NULL1;
- wf2rgbweight=NULL1;
- cmrgb=NULL1;
- newcol=NULL1;
- error=NULL1;
- error2=NULL1;
- nrestricted=0;
- restrict_changes= -1;
- }
-
-
- void
- decide_mode(void)
- {
- float sx, sy, st;
-
- if (directrgb>=0) {
- if (directrgb%3)
- error1(E0_FATAL, E1_IFF_RGB, E2_OPTION, E3_WRONG_NR_PLANES, (int)directrgb);
- nplanes=directrgb;
- printe("IFF output; direct rgb, %d planes\n", nplanes);
- return;
- }
- if ((xmode!=UNSET || ymode!=UNSET) && asc)
- error0(E0_FATAL, E1_IFF, E2_OPTION, E3_ASC);
- if (xmode!=UNSET && hires!=HIRES_OK)
- error0(E0_FATAL, E1_IFF, E2_OPTION, E3_NOHIRES);
- count_pixels(0, (int)ysz-1, 1);
- ticolors=icolors=count_colors(1L);
- if (hires==HIRES_MAYBE)
- hires=(icolors<=16 ? HIRES_OK : HIRES_NOT);
- if (asc && (xsz>scrw || ysz>scrh)) {
- sx=(float)scrw/(float)xsz;
- sy=(float)scrh/(float)ysz;
- if (sy<sx)
- st=sy;
- else
- st=sx;
- ymode=LACE;
- sy=st*2.0;
- if (hires==HIRES_OK) {
- xmode=HIRES;
- sx=st*2.0;
- } else {
- sx=st;
- if (sy>1.0) {
- sx=sx/sy;
- sy=1.0;
- }
- }
- if (sx!=sy || sx<1.0) {
- scalef(1, sy);
- scalef(0, sx);
- }
- }
- if (xmode==UNSET) {
- if (icolors<=32)
- xmode=LORES;
- else
- xmode=HAM;
- }
- slicedo=sliced;
- if (ymode==UNSET)
- ymode=NOLACE;
- if (ymode==LACE && (ysz&1))
- do_enlarge((int)xsz, (int)ysz+1);
- if (distrmeth2!=DISTRMETH_UNSET && xmode!=HAM)
- error0(E0_FATAL, E1_IFF, E2_OPTION, E3_ITMETH);
- if (!inoperation && distrmeth==DISTRMETH_UNSET) {
- if (xmode==EHB)
- distrmeth=DEF_EHB_DISTRMETH;
- else
- distrmeth=DEF_DISTRMETH;
- }
- if (countmeth==COUNTMETH_UNSET)
- countmeth=(xmode==HAM ? DEF_HAM_COUNTMETH : DEF_COUNTMETH);
- if (xmode==EHB && !is_ehb_distr())
- error1(E0_FATAL, E1_IFF, E2_OPTION, E3_EHB_METH, dmethnam(distrmeth));
- printe("IFF output; xmode: %s%s, ymode: %s, cmeth: %s, dmeth: %s",
- mmapnam((int)sliced), xmodenam(xmode), ymodenam(ymode),
- cmethnam(countmeth), dmethnam(distrmeth));
- if (distrmeth2!=DISTRMETH_UNSET)
- printe(", dmeth2: %s", dmethnam(distrmeth2));
- pute('\n');
- }
-
-
- int
- is_ehb_distr(void)
- {
- return (distrmeth==DISTRMETH_EHB || distrmeth==DISTRMETH_MUE ? 1 : 0);
- }
-
-
- void
- compute_nregs(void)
- {
- if (directrgb>=0)
- return;
- switch (xmode) {
- case HAM: nregs=16; nplanes=6; break;
- case EHB: nregs=64; nplanes=6; break;
- case LORES: nregs=32; nplanes=5; break;
- case HIRES: nregs=16; nplanes=4; break;
- }
- if (slicedo) {
- cm=Malloc((ymode==LACE && sliced!=SLICED_DYN ? (ysz+1)/2 : ysz)*nregs*sizeof(u_short));
- curcm=cm;
- goto compute_npixvals;
- }
- count_pixels(0, (int)ysz-1, 0);
- icolors=count_colors(1L);
- if (icolors>nregs && threshold>1) {
- icolors=count_colors(threshold);
- if (icolors<nregs) {
- u_long mint, curt, maxt;
-
- printe("%d colors occur at least %ld times, trying to complete to %d\n",
- icolors, threshold, nregs);
- mint=1;
- maxt=threshold;
- while (maxt>mint+1) {
- curt=(mint+maxt)/2;
- icolors=count_colors(curt);
- if (icolors<nregs)
- maxt=curt-1;
- else
- mint=curt;
- }
- threshold=(mint+maxt)/2;
- icolors=count_colors(threshold);
- printe("%d colors occur at least %ld times\n", icolors, threshold);
- }
- }
- if (xmode==LORES || xmode==HIRES) {
- if (icolors<nregs)
- nplanes=ceillog2((u_long)icolors);
- else
- nplanes=ceillog2((u_long)nregs);
- nregs=1<<nplanes;
- }
- cm=Malloc(nregs*sizeof(u_short));
- curcm=cm;
- compute_npixvals:
- if (distrmeth2!=DISTRMETH_UNSET) {
- cm0=Malloc(nregs*sizeof(u_short));
- cmprev=Malloc(nregs*sizeof(u_short));
- }
- npixvals=1<<nplanes;
- printe("%d colors", ticolors);
- if (icolors!=ticolors)
- printe(", counting %d colors", icolors);
- printe(", %d color registers, %d planes", nregs, nplanes);
- if (nregs-icolors>0)
- printe(", %d registers wasted", nregs-icolors);
- pute('\n');
- if (nregs<2 || xsz<2 || ysz<2)
- error0(E0_FATAL, E1_IFF, E2_FORMAT, E3_2SIMPLE);
- assert(nplanes>0 && nplanes<=MAXNPLANES);
- assert(nregs<=MAXNREGS);
- }
-
-
- void
- write_header(void)
- {
- struct bmhd_t {
- u_short w, h;
- short x, y;
- u_char nplanes, masking, compression, pad;
- u_short transpcol;
- u_char xaspect, yaspect;
- short pagew, pageh;
- } bmhd;
- u_long viewmodes;
-
- wrl(id('B', 'M', 'H', 'D'));
- wrl((long)sizeof(bmhd));
- bmhd.w=xsz;
- bmhd.h=ysz;
- bmhd.x=bmhd.y=0;
- bmhd.nplanes=nplanes;
- bmhd.masking=0;
- bmhd.compression=compression;
- bmhd.pad=0;
- bmhd.transpcol=0;
- bmhd.yaspect=11;
- if (xmode==HIRES && ymode==NOLACE)
- bmhd.xaspect=5;
- else if (xmode!=HIRES && ymode==LACE)
- bmhd.xaspect=20;
- else
- bmhd.xaspect=10;
- bmhd.pagew=bmhd.w;
- bmhd.pageh=bmhd.h;
- cwrite(&bmhd, sizeof(bmhd));
- if (directrgb>=0)
- return;
- wrl(id('C', 'A', 'M', 'G'));
- wrl(4L);
- viewmodes=0;
- if (xmode==HIRES)
- viewmodes|=VM_HIRES;
- else if (xmode==HAM)
- viewmodes|=VM_HAM;
- else if (xmode==EHB)
- viewmodes|=VM_EHB;
- if (ymode==LACE)
- viewmodes|=VM_LACE;
- wrl(viewmodes);
- }
-
-
- void
- write_cmap(void)
- {
- u_char *cmbuf;
- long t;
- short i, j, nr;
- static long pos= -1;
-
- if (directrgb>=0)
- return;
- if (xmode==EHB)
- nr=nregs/2;
- else
- nr=nregs;
- t=nr*3;
- if (pos== -1) {
- wrl(id('C', 'M', 'A', 'P'));
- wrl(t);
- pos=cseek_out(0L, 1);
- } else
- cseek_out(pos, 0);
- cmbuf=Malloc(t);
- for (i=0, j=0; i<nr; ++i) {
- cmbuf[j++]=(cm[i]&0x0f00)>>4;
- cmbuf[j++]= cm[i]&0x00f0;
- cmbuf[j++]=(cm[i]&0x000f)<<4;
- }
- cwrite(cmbuf, (int)t);
- free(cmbuf);
- }
-
-
- void
- write_mmap(void)
- {
- long t;
- static long pos= -1;
-
- if (!slicedo)
- return;
- if (xmode==EHB)
- error0(E0_FATAL, E1_IFF, E2_EHB, E3_SLICED_EHB);
- t=(ymode==LACE && sliced!=SLICED_DYN ? (ysz+1)/2 : ysz)*nregs*sizeof(u_short);
- if (pos== -1) {
- pos=cseek_out(0L, 2);
- switch (sliced) {
- case SLICED_SHAM: {
- short ver;
-
- wrl(id('S', 'H', 'A', 'M'));
- wrl(t+2);
- ver=0;
- cwrite(&ver, 2);
- cwrite(cm, (int)t);
- } break;
- case SLICED_DYN:
- wrl(id('C', 'T', 'B', 'L'));
- wrl(t);
- cwrite(cm, (int)t);
- break;
- case SLICED_PCHG:
- mmap_size_known=0;
- break;
- default:
- assert(0);
- break;
- }
- } else {
- switch (sliced) {
- case SLICED_SHAM:
- cseek_out(pos+10, 0);
- cwrite(cm, (int)t);
- break;
- case SLICED_DYN:
- cseek_out(pos+8, 0);
- cwrite(cm, (int)t);
- break;
- case SLICED_PCHG:
- cseek_out(pos, 0);
- write_1pchg();
- break;
- }
- if (nrestricted)
- printe("restricting per line changes to %d made %lu changes unsatisfiable\n",
- restrict_changes, nrestricted);
- }
- }
-
-
- void
- write_1pchg(void)
- {
- short Compression, Flags, StartLine, LineCount;
- short ChangedLines, MinReg, MaxReg, MaxChanges;
- long TotalChanges;
- int firstchange, lastchange, nmaps, linemask_size, changes_size;
- u_short *cmptr, *cmptr2, *cmend;
- u_long *linemask;
- u_short *changes, *changesp, *changesp2;
- short i;
- int mapnum, regnum, nchanges, nchanges32;
- long linemask_index;
-
- assert(nregs<=32);
- nmaps=(ymode==LACE ? (ysz+1)/2 : ysz);
- /* compute firstchange, the mapnr of the first map different
- * from the first map
- */
- cmptr=cm;
- for (firstchange=0; firstchange<nmaps; ++firstchange) {
- cmptr2=cm;
- i=nregs-1;
- do {
- if (*cmptr++ != *cmptr2++)
- goto firstchange_found;
- } while (--i>=0);
- }
- firstchange_found:
- if (firstchange>=nmaps)
- return;
- /* compute lastchange, the mapnr of the last map different
- * from the last map, +1
- */
- cmend=cm+nregs*nmaps;
- cmptr=cmend;
- for (lastchange=nmaps-1; lastchange>=0; --lastchange) {
- cmptr2=cmend;
- i=nregs-1;
- do {
- if (*--cmptr != *--cmptr2)
- goto lastchange_found;
- } while (--i>=0);
- }
- lastchange_found:
- ++lastchange;
- /* fill in some of the header fields, allocate the linemask */
- Compression=PCHG_COMP_NONE;
- Flags=PCHGF_12BIT;
- StartLine=(ymode==LACE ? 2*firstchange : firstchange);
- LineCount=(ymode==LACE ? 2*lastchange : lastchange)-StartLine+1;
- linemask_size=(LineCount+31)/32*4;
- linemask=Calloc(linemask_size);
- /* compute the other header fields, fill linemask */
- ChangedLines=0;
- MinReg=nregs-1;
- MaxReg=0;
- MaxChanges=0;
- TotalChanges=0;
- cmptr=cm+firstchange*nregs;
- for (mapnum=firstchange; mapnum<=lastchange; ++mapnum) {
- cmptr2=cmptr-nregs;
- nchanges=0;
- for (regnum=0; regnum<nregs; ++regnum) {
- if (cmptr[regnum]!=cmptr2[regnum]) {
- ++nchanges;
- if (regnum<MinReg)
- MinReg=regnum;
- if (regnum>MaxReg)
- MaxReg=regnum;
- }
- }
- if (nchanges) {
- ++ChangedLines;
- if (nchanges>MaxChanges)
- MaxChanges=nchanges;
- TotalChanges+=nchanges;
- linemask_index=mapnum-firstchange;
- if (ymode==LACE)
- linemask_index<<=1;
- linemask[linemask_index>>5]|=1L<<(31-(linemask_index & 0x1f));
- }
- cmptr+=nregs;
- }
- /* allocate the changes */
- changes_size=(int)ChangedLines*2+TotalChanges*2;
- changes=Malloc(changes_size);
- /* fill changes */
- cmptr=cm+firstchange*nregs;
- changesp=changes;
- for (mapnum=firstchange; mapnum<=lastchange; ++mapnum) {
- cmptr2=cmptr-nregs;
- nchanges=0;
- nchanges32=0;
- changesp2=changesp+1;
- for (regnum=0; regnum<nregs; ++regnum) {
- if (cmptr[regnum]!=cmptr2[regnum]) {
- if (regnum<16)
- ++nchanges;
- else
- ++nchanges32;
- *changesp2++ =(regnum<<12)|cmptr[regnum];
- }
- }
- if (nchanges+nchanges32) {
- *changesp=(nchanges<<8)|nchanges32; /* BYTEORDER */
- changesp=changesp2;
- }
- cmptr+=nregs;
- }
- assert(changesp==(u_short *)((long)changes+changes_size));
- /* write the chunk */
- wrl(id('P', 'C', 'H', 'G'));
- wrl(20L+(long)linemask_size+(long)changes_size);
- wrs(Compression);
- wrs(Flags);
- wrs(StartLine);
- wrs(LineCount);
- wrs(ChangedLines);
- wrs(MinReg);
- wrs(MaxReg);
- wrs(MaxChanges);
- wrl(TotalChanges);
- cwrite(linemask, linemask_size);
- cwrite(changes, changes_size);
- /* deallocate data */
- free(linemask);
- free(changes);
- }
-
-
- void
- write_body(void)
- {
- static long tmpnum= -1;
- static long pos;
-
- if (tmpnum== -1) {
- if (mmap_size_known) {
- pos=cseek_out(0L, 2);
- write_1body();
- tmpnum= -2;
- } else {
- cout_tmp();
- write_1body();
- cout_default(&tmpnum, &pos); /* pos used as dummy here */
- }
- } else {
- long endpos;
-
- if (!mmap_size_known) {
- pos=cseek_out(0L, 2);
- ctmp_move(tmpnum);
- }
- endpos=cseek_out(0L, 2);
- cseek_out(pos+4, 0);
- wrl(endpos-pos-8);
- }
- }
-
-
- void
- write_1body(void)
- {
- int y, step;
- void (*outfunc)(int);
-
- if (directrgb<0)
- fillconv();
- if (xmode==HAM)
- assert(nplanes==6);
- if (!inoperation) {
- wrl(id('B', 'O', 'D', 'Y'));
- wrl(0L);
- }
- bytesperrow=(xsz+15)/16*2;
- noutrows=MAXOUTBUFSZ/(bytesperrow*nplanes);
- if (noutrows==0)
- noutrows=1;
- outbufsz=noutrows*bytesperrow*nplanes;
- outrows=Malloc(outbufsz);
- if (compression)
- outcrows=Malloc(outbufsz*3/2);
- body_size=0;
- curcm=cm;
- if (xmode==HAM) {
- fill_prgbtab();
- outfunc=ham_row_out;
- } else
- outfunc=row_out;
- if (directrgb>=0) {
- nzero=nplanes/3-4;
- if (nzero<0)
- nzero=0;
- ncolor=nplanes/3;
- if (ncolor>4)
- ncolor=4;
- init_counter(0, (int)ysz, 10, "writing RGB IFF");
- for (y=0; y<ysz; ++y)
- rgb_row_out(y);
- } else if (slicedo) {
- if (ymode==LACE && sliced!=SLICED_DYN)
- step=2;
- else
- step=1;
- init_counter(0, (int)ysz, 5, "writing multimap IFF");
- for (y=0; y<ysz; y+=step) {
- if (y==ysz-1)
- step=1;
- count_pixels(y, y+step-1, 0);
- icolors=count_colors(threshold);
- if (icolors<nregs && threshold>1)
- printe("in row %d (and %d) only %d colors occur at least %ld times\n",
- y, y+step-1, icolors, threshold);
- compute_distr(y, y+step-1);
- outfunc(y);
- if (step==2)
- outfunc(y+1);
- curcm+=nregs;
- }
- } else {
- compute_distr(0, (int)ysz-1);
- init_counter(0, (int)ysz, 10, "writing IFF");
- for (y=0; y<ysz; ++y)
- outfunc(y);
- }
- if (!inoperation)
- (void)next_row(1); /* to flush the row buffer */
- erase_counter(NULL);
- }
-
-
- void
- fillconv(void)
- {
- short i, j, k;
- u_char *p;
-
- conv=Malloc(npixvals*8*MAXNPLANES);
- p=conv;
- for (i=0; i<npixvals; ++i) {
- for (j=128; j; j>>=1) {
- for (k=0; k<nplanes; ++k) {
- if (i&(1<<k))
- *p++ =j;
- else
- *p++ =0;
- }
- p+=MAXNPLANES-nplanes;
- }
- }
- }
-
-
- int
- cmpcolregs(short *p1, short *p2)
- {
- short c1, c2, i;
-
- c1= *p1;
- c2= *p2;
- i=((c1>>8) + ((c1&0x00f0)>>4) + (c1&0x000f))
- - ((c2>>8) + ((c2&0x00f0)>>4) + (c2&0x000f));
- if (i)
- return (int)i;
- i=(c1>>8)-(c2>>8);
- if (i)
- return (int)i;
- i=((c1&0x00f0)>>4)-((c2&0x00f0)>>4);
- if (i)
- return (int)i;
- i=(c1&0x000f)-(c2&0x000f);
- return (int)i;
- }
-
-
- void
- sort_cm(void)
- {
- qsort((char *)curcm, (int)nregs, sizeof(u_short),
- (int (*)(void *, void *))cmpcolregs);
- }
-
-
- static char *qm="?";
-
- static char *sliceds[]={
- "ok",
- "not",
- "maybe",
- NULL
- };
-
- char *
- slicednam(int i)
- {
- if (i<0 || i>2)
- return qm;
- return sliceds[i];
- }
-
-
- static char *xmodes[]={
- "unset",
- "hires",
- "lores",
- "ehb",
- "ham",
- NULL
- };
-
- char *
- xmodenam(int i)
- {
- if (i<0 || i>4)
- return qm;
- return xmodes[i];
- }
-
-
- static char *ymodes[]={
- "unset",
- "lace",
- "nolace",
- NULL
- };
-
- char *
- ymodenam(int i)
- {
- if (i<0 || i>2)
- return qm;
- return ymodes[i];
- }
-
-
- /* should be in same order as DISTRMETH_ defines in wasp.h */
- static char *dmeths[]={
- "unset",
- "mu",
- "wf",
- "ehb",
- "mue",
- "hs",
- "con",
- NULL
- };
-
- char *
- dmethnam(int i)
- {
- if (i<0 || i>6)
- return qm;
- return dmeths[i];
- }
-
- int
- dmethnum(char *s)
- {
- int i;
-
- for (i=1; dmeths[i]; ++i)
- if (!strcmp(s, dmeths[i]))
- return i;
- return -1;
- }
-
-
- /* should be in same order as COUNTMETH_ defines in wasp.h */
- static char *cmeths[]={
- "unset",
- "all1",
- "alldif",
- "allfdif",
- "j1",
- "j21",
- "jdif",
- "jdifsh",
- "jfdif",
- "jfdifsh",
- "hmgs",
- "hmcubic",
- "hm",
- NULL
- };
-
- char *
- cmethnam(int i)
- {
- if (i<0 || i>12)
- return qm;
- return cmeths[i];
- }
-
- int
- cmethnum(char *s)
- {
- int i;
-
- for (i=1; cmeths[i]; ++i)
- if (!strcmp(s, cmeths[i]))
- return i;
- return -1;
- }
-
-
- static char *mmaps[]={
- "",
- "sliced ",
- "dynamic ",
- "multipalette ",
- NULL
- };
-
- char *
- mmapnam(int i)
- {
- assert(i>=0 && i<4);
- return mmaps[i];
- }
-