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 >
Wrap
C/C++ Source or Header
|
1991-10-19
|
16KB
|
712 lines
/* 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;
}
}
}