home *** CD-ROM | disk | FTP | other *** search
- /* wasp - Copyright 1991 by Steven Reiz
- * see COPYING and 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, 16/11/91,
- * 8/12/91, 27/12/91
- */
-
- static char *sourcefile=__FILE__;
-
- #include "wasp.h"
-
- 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 short dynamic=0; /* dynamic sliced (CTBL iso SHAM chunk) */
- 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;
- #define mskNone 0
- #define mskHasMask 1
- #define mskHasTransparentColor 2
- #define mskLasso 3
- static u_short *cmap, *curcmap;
- static u_short *sham=NULL;
- static short nplanes, ncmap, nregs, nsham, directrrgb=0;
- static short mask_plane;
-
-
- read_iff(void)
- {
- u_long id;
-
- cread(&id, (int)sizeof(id));
- if (!isgroupid(id)) {
- cseek_in(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);
- cseek_in(pos, 0);
- do_chunk(id);
- }
- if (!seen_body)
- error0(E0_FATAL, E1_IFF, E2_BODY, E3_MISS_CHUNK);
- free(cmap);
- return 1;
- }
-
-
- char *
- idstr(unsigned long id)
- {
- static char ids[5];
-
- *(u_long *)ids=id;
- ids[4]='\0';
- return ids;
- }
-
-
- void
- do_chunk(unsigned long id)
- {
- u_long size, t, newpos;
-
- cread(&size, (int)sizeof(size));
- size=(size+1) & -2;
- pos+=sizeof(size);
- if (isgroupid(id)) {
- cread(&t, (int)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, (int)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_ERROR, E1_IFF, E2_BMHD, E3_WRONGCHUNKSZ);
- cread(&bmhd, (int)sizeof(struct bmhd_t));
- 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_ERROR, E1_IFF, E2_CAMG, E3_WRONGCHUNKSZ);
- cread(&viewmodes, (int)sizeof(viewmodes));
- 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;
- dynamic=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);
- cseek_in(size, 1);
- pos+=size;
- }
- }
- }
-
-
- isgroupid(unsigned long id)
- {
- 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');
- }
-
-
- isgroupid2(unsigned long i, unsigned long i2)
- {
- char c;
-
- c=i;
- return i==i2 || ((i&0xffffff00L)==(i2&0xffffff00L) && c>='1' && c<='9');
- }
-
-
- isvalid(unsigned long id)
- {
- char *p;
- int i;
-
- for (p=(char *)&id, i=0; i<4; ++i)
- if (*p<' ' || *p>'~')
- break;
- else
- ++p;
- return i>=4;
- }
-
-
- void
- do_anno(unsigned long size)
- {
- short i;
- char *anno;
-
- anno=Malloc(size+1);
- cread(anno, (int)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;
- }
-
-
- void
- do_cmap(unsigned long size)
- {
- 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, (int)sizeof(filergb));
- cmap[i]=((u_short)filergb[0]&0xf0)<<4 | filergb[1]&0xf0 | (u_long)filergb[2]>>4;
- }
- pos+=size;
- }
-
-
- void
- extend_cmap(void)
- {
- 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;
- }
-
-
- void
- do_sham(unsigned long size, int is_ctbl)
- {
- 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;
- }
-
-
- void
- do_body(unsigned long size)
- {
- short y;
-
- xsz=bmhd.w;
- ysz=bmhd.h;
- nregs=1<<nplanes;
- if (viewmodes & VM_HAM)
- nregs=16;
- if (bmhd.masking==mskHasMask) {
- error0(E0_WARNING, E1_IFF, E2_FORMAT, E3_MASKING);
- mask_plane=1;
- } else
- mask_plane=0;
- 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_ERROR, E1_IFF_RGB, E2_CAMG, E3_UNEXP_CHUNK);
- if (sham)
- error0(E0_ERROR, 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);
- }
- printe("IFF input; %ld x %ld, %d plane%s, ", xsz, ysz, (int)nplanes,
- (nplanes==1 ? "" : "s"));
- if (viewmodes & VM_LACE)
- printe("interlaced ");
- if (sham)
- printe("%s%s ", (laced_sham ? "lace-" : ""),
- (dynamic ? "dynamic" : "sliced"));
- if (directrrgb)
- printe("direct rgb\n");
- else if (viewmodes & VM_EHB)
- printe("ehb\n");
- else if (viewmodes & VM_HAM)
- printe("ham\n");
- else if (viewmodes & VM_HIRES)
- printe("hires\n");
- else
- printe("lores\n");
- if (!outfilename)
- exit(0);
- rgb=Malloc(ysz*sizeof(u_short *));
- for (y=0; y<ysz; ++y)
- rgb[y]=Calloc(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;
-
- void
- set_bodylimit(unsigned long size)
- {
- bodylimit=size;
- bodypos=0;
- }
-
-
- void
- check_bodylimit(void)
- {
- if (bodypos!=bodylimit)
- error0(E0_ERROR, E1_IFF, E2_BODY, E3_UNSPEC);
- }
-
-
- short
- nextbody(void *buf)
- {
- int toread;
-
- toread=bodylimit-bodypos;
- if (toread<=0) {
- error1(E0_ERROR, E1_IFF, E2_BODY, E3_UNEXPEND, "chunk");
- return 0;
- }
- if (toread>RBBUFSZ)
- toread=RBBUFSZ;
- cread_type=CREAD_NONFATAL;
- cread(buf, toread);
- cread_type=CREAD_STRICT;
- if (cread_result<=0)
- return 0;
- if (cread_result!=toread)
- toread=cread_result;
- bodypos+=toread;
- return (short)toread;
- }
-
-
-
- void
- read_direct_body(void)
- {
- short bufn, x, y, z, planei;
- u_char *buf, *bufp;
- char *row, *q, c;
-
- init_counter(0, (int)ysz, 10, "reading RGB IFF");
- row=Malloc((nplanes+mask_plane)*((xsz+15)/16)*2+128);
- buf=Malloc(RBBUFSZ);
- bufn=0;
- for (y=0; y<ysz; ++y) {
- counter();
- for (planei=0; planei<nplanes+mask_plane; ++planei) {
- if (bmhd.compression) {
- x=(xsz+15)/16*2;
- q=row+planei*x;
- while (x>0) {
- if (--bufn<0) {
- bufn=nextbody(buf)-1;
- if (bufn<0)
- goto quit_read_direct_body;
- bufp=buf;
- }
- z= *bufp++;
- if (z<=127) {
- x-=z;
- --x;
- while (z>=0) {
- if (--bufn<0) {
- bufn=nextbody(buf)-1;
- if (bufn<0)
- goto quit_read_direct_body;
- bufp=buf;
- }
- *q++ = *bufp++;
- --z;
- }
- } else if (z==128) {
- /* do nothing */
- } else {
- z=257-z;
- x-=z;
- if (--bufn<0) {
- bufn=nextbody(buf)-1;
- if (bufn<0)
- goto quit_read_direct_body;
- bufp=buf;
- }
- c= *bufp++;
- while (--z>=0)
- *q++ =c;
- }
- }
- if (x!=0)
- error0(E0_ERROR, E1_IFF, E2_COMPRESSION, E3_ROWBOUND);
- } else {
- for (x=(xsz+15)/16*2-1, q=row+planei*((xsz+15)/16*2); x>=0; --x) {
- if (--bufn<0) {
- bufn=nextbody(buf)-1;
- if (bufn<0)
- goto quit_read_direct_body;
- bufp=buf;
- }
- *q++ = *bufp++;
- }
- }
- }
- do_row_direct(y, (u_char *)row);
- }
- quit_read_direct_body:
- free(row);
- free(buf);
- }
-
-
- void
- read_body(void)
- {
- short bufn, x, y;
- long lon;
- short z;
- u_char *buf, *bufp;
- u_long *p, *q, *row;
-
- init_counter(0, (int)ysz, 20, "reading IFF");
- if (sham)
- curcmap=sham;
- else
- curcmap=cmap;
- row=Malloc(8*(xsz+15)/16*2+128);
- buf=Malloc(RBBUFSZ);
- bufn=0;
- conv=Malloc((nplanes+mask_plane)*256*8);
- fill_conv();
- for (y=0; y<ysz; ++y) {
- counter();
- for (lon=(long)conv; lon<(long)conv+(nplanes+mask_plane)*256*8; lon+=256*8) {
- if (bmhd.compression) {
- x=(xsz+15)/16*2;
- q=row;
- while (x>0) {
- if (--bufn<0) {
- bufn=nextbody(buf)-1;
- if (bufn<0)
- goto quit_read_body;
- bufp=buf;
- }
- z= *bufp++;
- if (z<=127) {
- x-=z;
- --x;
- while (z>=0) {
- if (--bufn<0) {
- bufn=nextbody(buf)-1;
- if (bufn<0)
- goto quit_read_body;
- bufp=buf;
- }
- p=(u_long *)(lon+(*bufp++ <<3));
- if (lon==(long)conv) {
- *q++ = *p++;
- *q++ = *p;
- } else {
- *q++ |= *p++;
- *q++ |= *p;
- }
- --z;
- }
- } else if (z==128) {
- /* do nothing */
- } else {
- z=257-z;
- x-=z;
- if (--bufn<0) {
- bufn=nextbody(buf)-1;
- if (bufn<0)
- goto quit_read_body;
- bufp=buf;
- }
- p=(u_long *)(lon+(*bufp++ <<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_ERROR, E1_IFF, E2_COMPRESSION, E3_ROWBOUND);
- } else {
- for (x=(xsz+15)/16*2-1, q=row; x>=0; --x) {
- if (--bufn<0) {
- bufn=nextbody(buf)-1;
- if (bufn<0)
- goto quit_read_body;
- bufp=buf;
- }
- p=(u_long *)(lon+(*bufp++ <<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;
- }
- quit_read_body:
- free(conv);
- free(row);
- free(buf);
- }
-
-
- void
- fill_conv(void)
- {
- 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;
- }
- }
- }
- if (mask_plane) {
- for (x=0; x<256; ++x)
- for (j=128; j; j>>=1)
- *p++ =0;
- }
- free(powtab);
- }
-
-
- void
- do_row(short y, unsigned char *parrow)
- {
- u_short *rgbrow;
- u_char *row;
- short x;
-
- rgbrow=rgb[y];
- row=parrow;
- for (x=xsz-1; x>=0; --x)
- *rgbrow++ =curcmap[*row++];
- }
-
-
- void
- do_row_ham(short y, unsigned char *parrow)
- {
- 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);
- }
-
-
- void
- do_row_direct(short y, unsigned char *inrow)
- {
- 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;
- }
- }
- }
-