home *** CD-ROM | disk | FTP | other *** search
- /* wasp - copyright Steven Reiz 1990, 1991
- * see wasp.c for further info
- * readiff.c, 4/12/90 - 31/12/90,
- * 5/5/91 - 2/6/91, 23/6/91, 9/7/91
- */
-
- #include "wasp.h"
- #ifndef NOSH
- #include "readiff.sh"
- #endif
-
- static u_long pos;
- static short seen_bmhd, seen_cmap, seen_sham, seen_camg, seen_body;
- static short laced_sham=0; /* one sham entry per two lines in lace mode */
- static u_long viewmodes=0;
- static 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;
- static u_short *cmap, *curcmap;
- static u_short *sham=NULL;
- static short nplanes, ncmap, nregs, nsham, directrrgb=0;
-
-
- #ifdef __STDC__
- read_iff(void)
- #else
- read_iff()
- #endif
- {
- u_long id;
-
- cread(&id, sizeof(id));
- if (!isgroupid(id)) {
- lseek(infd, 0L, 0);
- return 0;
- }
- pos=sizeof(id);
- seen_bmhd=seen_cmap=seen_sham=seen_camg=seen_body=0;
- do_chunk(id);
- if (!seen_bmhd)
- error0(E0_FATAL, E1_IFF, E2_BMHD, E3_MISS_CHUNK);
- if (!seen_body) {
- if (!seen_camg) {
- error0(E0_WARNING, E1_IFF, E2_CAMG, E3_MISS_CHUNK);
- viewmodes=(nplanes==6 ? VM_HAM : 0);
- seen_camg=1;
- }
- pos=sizeof(id);
- lseek(infd, pos, 0);
- do_chunk(id);
- }
- if (!seen_body)
- error0(E0_FATAL, E1_IFF, E2_BODY, E3_MISS_CHUNK);
- free(cmap);
- return 1;
- }
-
-
- #ifdef __STDC__
- PRIVATE char *idstr(u_long id)
- #else
- PRIVATE char *idstr(id)
- u_long id;
- #endif
- {
- static char ids[5];
-
- *(u_long *)ids=id;
- ids[4]='\0';
- return ids;
- }
-
-
- #ifdef __STDC__
- PRIVATE do_chunk(u_long id)
- #else
- PRIVATE do_chunk(id)
- u_long id;
- #endif
- {
- u_long size, t, newpos;
-
- cread(&size, sizeof(size));
- size=(size+1) & -2;
- pos+=sizeof(size);
- if (isgroupid(id)) {
- cread(&t, sizeof(t));
- pos+=sizeof(t);
- if (size<0)
- error0(E0_FATAL, E1_IFF, E2_FORMAT, E3_NEGGROUPSIZE);
- newpos=pos+size-sizeof(t);
- while (pos<newpos) {
- u_long pid;
-
- cread(&pid, sizeof(pid));
- pos+=sizeof(pid);
- if (!isvalid(pid))
- error0(E0_FATAL, E1_IFF, E2_FORMAT, E3_INVALID_ID);
- else
- do_chunk(pid);
- }
- if (pos>newpos)
- error0(E0_FATAL, E1_IFF, E2_FORMAT, E3_GROUP2SMALL);
- } else {
- /* normal chunks */
- if (id==id('B', 'M', 'H', 'D') && !seen_bmhd) {
- seen_bmhd=1;
- if (size!=sizeof(struct bmhd_t))
- error0(E0_FATAL, E1_IFF, E2_BMHD, E3_WRONGCHUNKSZ);
- cread(&bmhd, (int)size);
- nplanes=bmhd.nplanes;
- pos+=size;
- } else if (id==id('C', 'A', 'M', 'G') && !seen_camg) {
- int nrmodes;
-
- seen_camg=1;
- if (size!=sizeof(viewmodes))
- error0(E0_FATAL, E1_IFF, E2_CAMG, E3_WRONGCHUNKSZ);
- cread(&viewmodes, (int)size);
- nrmodes=0;
- if (viewmodes & VM_EHB)
- ++nrmodes;
- if (viewmodes & VM_HAM)
- ++nrmodes;
- if (viewmodes & VM_HIRES)
- ++nrmodes;
- if (nrmodes>1)
- error0(E0_FATAL, E1_IFF, E2_CAMG, E3_CAMGMODES);
- pos+=size;
- } else if (id==id('C', 'M', 'A', 'P') && !seen_cmap) {
- seen_cmap=1;
- do_cmap(size);
- } else if (id==id('S', 'H', 'A', 'M') && !seen_sham) {
- seen_sham=1;
- do_sham(size, 0);
- } else if (id==id('C', 'T', 'B', 'L') && !seen_sham) {
- seen_sham=1;
- do_sham(size, 1);
- } else if (id==id('B', 'O', 'D', 'Y')
- && !seen_body && seen_bmhd) {
- seen_body=1;
- do_body(size);
- } else if (id==id('A', 'N', 'N', 'O')) {
- do_anno(size);
- } else { /* skip unknown chunks */
- error2(E0_WARNING, E1_IFF, E2_FORMAT, E3_UNKNOWN_CHUNK, idstr(id), size);
- lseek(infd, size, 1);
- pos+=size;
- }
- }
- }
-
-
- #ifdef __STDC__
- PRIVATE int isgroupid(u_long id)
- #else
- PRIVATE int isgroupid(id)
- u_long id;
- #endif
- {
- return isgroupid2(id, id('F', 'O', 'R', 'M')) ||
- isgroupid2(id, id('L', 'I', 'S', 'T')) ||
- isgroupid2(id, id('C', 'A', 'T', ' ')) ||
- id==id('P', 'R', 'O', 'P');
- }
-
-
- #ifdef __STDC__
- PRIVATE int isgroupid2(u_long i, u_long i2)
- #else
- PRIVATE int isgroupid2(i, i2)
- u_long i, i2;
- #endif
- {
- char c;
-
- c=i;
- return i==i2 || ((i&0xffffff00L)==(i2&0xffffff00L) && c>='1' && c<='9');
- }
-
-
- #ifdef __STDC__
- PRIVATE int isvalid(u_long id)
- #else
- PRIVATE int isvalid(id)
- u_long id;
- #endif
- {
- char *p;
- int i;
-
- for (p=(char *)&id, i=0; i<4; ++i)
- if (*p<' ' || *p>'~')
- break;
- else
- ++p;
- return i>=4;
- }
-
-
- #ifdef __STDC__
- PRIVATE do_anno(u_long size)
- #else
- PRIVATE do_anno(size)
- u_long size;
- #endif
- {
- short i;
- char *anno;
-
- anno=Malloc(size+1);
- cread(anno, size);
- anno[size]='\0';
- for (i=0; i<size; ++i) {
- if (i==size-1 && !anno[i])
- break;
- if (anno[i]<' ' || anno[i]>'~')
- anno[i]='.';
- }
- printe("ANNO: %s\n", anno);
- free(anno);
- pos+=size;
- }
-
-
- #ifdef __STDC__
- PRIVATE do_cmap(u_long size)
- #else
- PRIVATE do_cmap(size)
- u_long size;
- #endif
- {
- u_char filergb[3];
- short i;
-
- if (size%6)
- error0(E0_FATAL, E1_IFF, E2_CMAP, E3_WRONGCHUNKSZ);
- ncmap=size/sizeof(filergb);
- cmap=Malloc(ncmap*sizeof(u_short));
- for (i=0; i<ncmap; ++i) {
- cread(filergb, sizeof(filergb));
- cmap[i]=((u_short)filergb[0]&0xf0)<<4 | filergb[1]&0xf0 | (u_long)filergb[2]>>4;
- }
- pos+=size;
- }
-
-
- #ifdef __STDC__
- PRIVATE extend_cmap(void)
- #else
- PRIVATE extend_cmap()
- #endif
- {
- u_short *newcmap, rgb;
- u_char r, g, b;
- short i;
-
- newcmap=Malloc(2*ncmap*sizeof(u_short));
- for (i=0; i<ncmap; ++i) {
- rgb=cmap[i];
- newcmap[i]=rgb;
- r=(rgb&0x0f00)>>9;
- g=(rgb&0x00f0)>>5;
- b=(rgb&0x000f)>>1;
- newcmap[i+ncmap]=(r<<8)|(g<<4)|b;
- }
- free(cmap);
- cmap=newcmap;
- ncmap*=2;
- }
-
-
- #ifdef __STDC__
- PRIVATE do_sham(u_long size, int is_ctbl)
- #else
- PRIVATE do_sham(size, is_ctbl)
- u_long size;
- int is_ctbl;
- #endif
- {
- short i;
-
- pos+=size;
- if (!is_ctbl) {
- cread(&i, 2);
- if (i)
- error1(E0_WARNING, E1_IFF, E2_SHAM, E3_UNKNOWN_VERSION, (int)i);
- size-=2;
- }
- sham=Malloc(size);
- cread(sham, (int)size);
- nsham=size/2;
- for (i=0; i<nsham; ++i)
- sham[i]&=0x0fff;
- }
-
-
- #ifdef __STDC__
- PRIVATE do_body(u_long size)
- #else
- PRIVATE do_body(size)
- u_long size;
- #endif
- {
- short y;
-
- xsz=bmhd.w;
- ysz=bmhd.h;
- nregs=1<<nplanes;
- if (viewmodes & VM_HAM)
- nregs=16;
- if (bmhd.masking)
- error0(E0_FATAL, E1_IFF, E2_FORMAT, E3_MASKING);
- if (bmhd.compression!=0 && bmhd.compression!=1)
- error1(E0_FATAL, E1_IFF, E2_COMPRESSION, E3_UNKNOWN_VERSION, (int)bmhd.compression);
- if (viewmodes & VM_HAM) {
- if (ncmap!=nregs)
- error1(E0_WARNING, E1_IFF, E2_HAM, E3_WRONG_NR_CREGS, (int)ncmap);
- if (nplanes!=6)
- error1(E0_FATAL, E1_IFF, E2_HAM, E3_WRONG_NR_PLANES, (int)nplanes);
- } else if (viewmodes & VM_EHB) {
- if (nplanes!=6)
- error1(E0_FATAL, E1_IFF, E2_EHB, E3_WRONG_NR_PLANES, (int)nplanes);
- extend_cmap();
- } else if (!seen_cmap) {
- directrrgb=1;
- if (seen_camg)
- error0(E0_FATAL, E1_IFF_RGB, E2_CAMG, E3_UNEXP_CHUNK);
- if (sham)
- error0(E0_FATAL, E1_IFF_RGB, E2_SHAM, E3_UNEXP_CHUNK);
- if (nplanes<12 || nplanes%3)
- error1(E0_FATAL, E1_IFF_RGB, E2_FORMAT, E3_WRONG_NR_PLANES, (int)nplanes);
- } else {
- if (ncmap!=(1<<nplanes))
- error2(E0_FATAL, E1_IFF, E2_FORMAT, E3_CREGS_PLANES, (int)ncmap,
- (int)nplanes);
- }
- if (sham) {
- int i;
-
- if (viewmodes & VM_EHB)
- error0(E0_FATAL, E1_IFF, E2_EHB, E3_SLICED_EHB);
- i=ysz;
- if ((viewmodes & VM_LACE) && nregs*i!=nsham) {
- i=(ysz+1)/2;
- laced_sham=1;
- }
- if (nregs*i!=nsham)
- error2(E0_FATAL, E1_IFF, E2_SHAM, E3_NENTRIES, (int)nsham, nregs*i);
- }
- printf("IFF input; %ld x %ld, %d plane%s, ", xsz, ysz, (int)nplanes,
- (nplanes==1 ? "" : "s"));
- if (viewmodes & VM_LACE)
- printf("interlaced ");
- if (sham)
- printf("%ssliced ", (laced_sham ? "lace-" : ""));
- if (directrrgb)
- printf("direct rgb\n");
- else if (viewmodes & VM_EHB)
- printf("ehb\n");
- else if (viewmodes & VM_HAM)
- printf("ham\n");
- else if (viewmodes & VM_HIRES)
- printf("hires\n");
- else
- printf("lores\n");
- fflush(stdout);
- if (!outfilename)
- exit(0);
- rgb=Malloc(ysz*sizeof(u_short *));
- for (y=0; y<ysz; ++y)
- rgb[y]=Malloc(xsz*sizeof(u_short));
- set_bodylimit(size);
- if (directrrgb)
- read_direct_body();
- else
- read_body();
- check_bodylimit();
- pos+=size;
- erase_counter(NULL);
- }
-
-
- static u_long bodylimit, bodypos;
- #define RBBUFSZ 32760
- static u_char *conv;
-
- #ifdef __STDC__
- PRIVATE set_bodylimit(u_long size)
- #else
- PRIVATE set_bodylimit(size)
- u_long size;
- #endif
- {
- bodylimit=size;
- bodypos=0;
- }
-
-
- #ifdef __STDC__
- PRIVATE check_bodylimit(void)
- #else
- PRIVATE check_bodylimit()
- #endif
- {
- if (bodypos!=bodylimit)
- error0(E0_FATAL, E1_IFF, E2_BODY, E3_UNSPEC);
- }
-
-
- #ifdef __STDC__
- PRIVATE short nextbody(void *buf)
- #else
- PRIVATE short nextbody(buf)
- void *buf;
- #endif
- {
- int toread;
-
- toread=bodylimit-bodypos;
- if (toread<=0)
- error0(E0_FATAL, E1_IFF, E2_BODY, E3_UNEXPEND);
- if (toread>RBBUFSZ)
- toread=RBBUFSZ;
- cread(buf, toread);
- bodypos+=toread;
- return (short)toread;
- }
-
-
- #define nextc() (bufi<bufsz ? buf[bufi++] : ((bufsz=nextbody(buf)), (bufi=1), buf[0]))
-
-
- #ifdef __STDC__
- PRIVATE read_direct_body(void)
- #else
- PRIVATE read_direct_body()
- #endif
- {
- short bufi, bufsz, x, y, z, planei;
- u_char *buf;
- char *row, *q, c;
-
- init_counter(0, (int)ysz, 10, NULL);
- row=Malloc(nplanes*((xsz+7)/8));
- buf=Malloc(RBBUFSZ);
- bufi=bufsz=0;
- for (y=0; y<ysz; ++y) {
- counter();
- for (planei=0; planei<nplanes; ++planei) {
- if (bmhd.compression) {
- x=(xsz+7)/8;
- q=row+planei*x;
- while (x>0) {
- z=nextc();
- if (z<=127 && (x-=z, --x, x>=0)) {
- while (z>=0) {
- *q++ =nextc();
- --z;
- }
- } else if (z==128) {
- /* do nothing */
- } else if (z<=255 && (z=257-z, x-=z, x>=0)) {
- c=nextc();
- while (--z>=0)
- *q++ =c;
- }
- }
- if (x!=0)
- error0(E0_FATAL, E1_IFF, E2_COMPRESSION, E3_ROWBOUND);
- } else {
- if (bufi&1) {
- nextc();
- }
- for (x=(xsz+7)/8-1, q=row+planei*((xsz+7)/8); x>=0; --x)
- *q++ =nextc();
- }
- }
- do_row_direct(y, (u_char *)row);
- }
- if (bufi&1)
- nextc();
- free(row);
- free(buf);
- }
-
-
- #ifdef __STDC__
- PRIVATE read_body(void)
- #else
- PRIVATE read_body()
- #endif
- {
- short bufi, bufsz, x, y;
- long lon;
- short z;
- u_char *buf;
- u_long *p, *q, *row;
-
- init_counter(0, (int)ysz, 20, NULL);
- if (sham)
- curcmap=sham;
- else
- curcmap=cmap;
- row=Malloc((xsz+7)/8*8);
- buf=Malloc(RBBUFSZ);
- bufi=bufsz=0;
- conv=Malloc(nplanes*256*8);
- fill_conv();
- for (y=0; y<ysz; ++y) {
- counter();
- for (lon=(long)conv; lon<(long)conv+nplanes*256*8; lon+=256*8) {
- if (bmhd.compression) {
- x=(xsz+7)/8;
- q=row;
- while (x>0) {
- z=nextc();
- if (z<=127 && (x-=z, --x, x>=0)) {
- while (z>=0) {
- p=(u_long *)(lon+(nextc()<<3));
- if (lon==(long)conv) {
- *q++ = *p++;
- *q++ = *p;
- } else {
- *q++ |= *p++;
- *q++ |= *p;
- }
- --z;
- }
- } else if (z==128) {
- /* do nothing */
- } else if (z<=255 && (z=257-z, x-=z, x>=0)) {
- p=(u_long *)(lon+(nextc()<<3));
- if (lon==(long)conv) {
- while (--z>=0) {
- *q++ = *p++;
- *q++ = *p;
- --p;
- }
- } else {
- while (--z>=0) {
- *q++ |= *p++;
- *q++ |= *p;
- --p;
- }
- }
- }
- }
- if (x!=0)
- error0(E0_FATAL, E1_IFF, E2_COMPRESSION, E3_ROWBOUND);
- } else {
- if (bufi&1)
- nextc();
- for (x=(xsz+7)/8-1, q=row; x>=0; --x) {
- p=(u_long *)(lon+(nextc()<<3));
- if (lon==(long)conv) {
- *q++ = *p++;
- *q++ = *p;
- } else {
- *q++ |= *p++;
- *q++ |= *p;
- }
- }
- }
- }
- if (viewmodes & VM_HAM)
- do_row_ham(y, (u_char *)row);
- else
- do_row(y, (u_char *)row);
- if (sham && (!laced_sham || !(y&1)))
- curcmap+=nregs;
- }
- if (bufi&1)
- nextc();
- free(conv);
- free(row);
- free(buf);
- }
-
-
- #ifdef __STDC__
- PRIVATE fill_conv(void)
- #else
- PRIVATE fill_conv()
- #endif
- {
- u_char *powtab, *p;
- short x, y;
- char i;
- short j;
-
- powtab=Malloc(8);
- p=powtab;
- for (i=1; i; i<<=1)
- *p++ =i;
- p=conv;
- for (y=0; y<nplanes; ++y) {
- for (x=0; x<256; ++x) {
- for (j=128; j; j>>=1) {
- if (j&x)
- *p++ =powtab[y];
- else
- *p++ =0;
- }
- }
- }
- free(powtab);
- }
-
-
- #ifdef __STDC__
- PRIVATE do_row(short y, u_char *parrow)
- #else
- PRIVATE do_row(y, parrow)
- short y;
- u_char *parrow;
- #endif
- {
- u_short *rgbrow;
- u_char *row;
- short x;
-
- rgbrow=rgb[y];
- row=parrow;
- for (x=xsz-1; x>=0; --x)
- *rgbrow++ =curcmap[*row++];
- }
-
-
- #ifdef __STDC__
- PRIVATE do_row_ham(short y, u_char *parrow)
- #else
- PRIVATE do_row_ham(y, parrow)
- short y;
- u_char *parrow;
- #endif
- {
- u_short *rgbrow;
- u_char *row, pixel;
- short x;
- u_short curcolor;
-
- rgbrow=rgb[y];
- row=parrow;
- curcolor=curcmap[0];
- x=xsz-1;
- do {
- pixel= *row++;
- if (pixel&0x20) {
- if (pixel&0x10) { /* modify green */
- curcolor=(curcolor&0x0f0f)|((pixel&0x0f)<<4);
- } else { /* modify red */
- curcolor=(curcolor&0x00ff)|((pixel&0x0f)<<8);
- }
- } else {
- if (pixel&0x10) { /* modify blue */
- curcolor=(curcolor&0x0ff0)|(pixel&0x0f);
- } else { /* use curcmap */
- curcolor=curcmap[pixel];
- }
- }
- *rgbrow++ =curcolor;
- } while (--x>=0);
- }
-
-
- #ifdef __STDC__
- PRIVATE do_row_direct(short y, u_char *inrow)
- #else
- PRIVATE do_row_direct(y, inrow)
- short y;
- u_char *inrow;
- #endif
- {
- u_short color, *dest;
- long x, bytesperscan, plane0;
- u_char *p, pmask, *plane1, *plane2, *plane3;
-
- dest=rgb[y];
- bytesperscan=(xsz+7)/8;
- plane0=nplanes/3*bytesperscan;
- for (x=0; x<bytesperscan; ++x) {
- plane1=inrow+x+plane0-bytesperscan;
- plane2=plane1+plane0;
- plane3=plane2+plane0;
- for (pmask=128; pmask; pmask=(unsigned long)pmask>>1) {
- color=0;
- p=plane1;
- if (*p & pmask) color|=0x0800; p-=bytesperscan;
- if (*p & pmask) color|=0x0400; p-=bytesperscan;
- if (*p & pmask) color|=0x0200; p-=bytesperscan;
- if (*p & pmask) color|=0x0100;
- p=plane2;
- if (*p & pmask) color|=0x0080; p-=bytesperscan;
- if (*p & pmask) color|=0x0040; p-=bytesperscan;
- if (*p & pmask) color|=0x0020; p-=bytesperscan;
- if (*p & pmask) color|=0x0010;
- p=plane3;
- if (*p & pmask) color|=0x0008; p-=bytesperscan;
- if (*p & pmask) color|=0x0004; p-=bytesperscan;
- if (*p & pmask) color|=0x0002; p-=bytesperscan;
- if (*p & pmask) color|=0x0001;
- *dest++ =color;
- }
- }
- }
-