
#include <exec/types.h>             /*for type defs*/
#include  <intuition/intuition.h>   /*for screens,windows*/
#include  <stdio.h>                 /*for printf*/

char *ilbm = "ILBM";                /*chunk identifiers*/
char *bmhd = "BMHD";
char *cmap = "CMAP";
char *body = "BODY";
char *acbm = "ACBM";
char *abit = "ABIT";

long bytesread;          /*bytes read from file*/
long totalbytes;         /*total bytes on file*/
long icLen;              /*chunk length*/
short iHeight,iWidth;    /*height and width of picture*/
short scrWidth,scrHeight;/*height and width of its screen*/
short iDepth;            /*number of bitplanes*/
short nColors;          /*number of colours*/
short iRowBytes;         /*picture bytes per row*/
short scrRowBytes;       /*pic screen bytes per row*/
UBYTE iCompr;            /*compression flag*/
UBYTE mybuf[120];        /*buffer for headers and short
                          chunks*/
USHORT colormap[60];     /*colourmap*/
USHORT colormap2[60];
long rLen;               /*bytes read from disc*/
char *tempbuffer;        /*temporary buffer for body chunk*/
long fHandle;            /*file handle*/
short red,gre,blu;        /*temporary colour variables*/
int camgModes;           /*camg modes*/


void fadedown(),fadeup();

FreeBitMap(bitmap)
struct BitMap *bitmap;
{
long  i,depth,bytes,rows;
depth=(bitmap->Depth)&255;
bytes=(bitmap->BytesPerRow)&0xffff;
rows=(bitmap->Rows)&0xffff;
for (i=0;i<depth;i++)
 {
  FreeRaster(bitmap->Planes[i],8*bytes,rows);
 }
return(0);
}

readfile(name,bitmap,viewport,code)
char *name;                     /*filename*/
struct BitMap *bitmap;          /*bitmap to be used*/
struct ViewPort *viewport;      /*viewport address*/
long code;                      /*colour change flag*/
{
openfile(name);
                                /*header*/
while (bytesread<totalbytes) readchunk(bitmap,viewport,code);
return(0);
}

/*open the iff file and read the header.Store the length*/
/*and check for an ILBM or ACBM file*/
openfile(filename)
char *filename;
{
fHandle = Open(filename,1005);
if (fHandle == NULL) return(FALSE);
rLen = Read(fHandle,&mybuf[0],12);
bytesread=rLen;
totalbytes=256*256*mybuf[5]+256*mybuf[6]+mybuf[7];
if((strcmp(ilbm,&mybuf[0]+8)) == 0) return(TRUE);
if ((strcmp(acbm,&mybuf[0]+8))==0)  return(TRUE);
return (FALSE);
}
readchunk(bitmap,viewport,code)
struct BitMap *bitmap;
struct ViewPort *viewport;
long code;
{
rLen = Read(fHandle,&mybuf[0],8);
icLen=mybuf[7]+256*mybuf[6];
bytesread=8+bytesread;
bytesread=icLen+bytesread;
if ((strcmp(bmhd,&mybuf)) == NULL)
 {readbitmapheader(bitmap,code);return(0);}
if ((strcmp(cmap,&mybuf[0])) == NULL) {readcmap(viewport,code);return(0);}
if ((strcmp(body,&mybuf[0])) == NULL) {readbody(bitmap);return(0);}
if ((strcmp(abit,&mybuf[0])) == NULL) {readbody(bitmap);return(0);}
rLen = Read(fHandle,&mybuf[0],icLen);
return(0);
}

readbitmapheader(bitmap,code)
struct BitMap *bitmap;
long code;
{
int i;
rLen = Read(fHandle,&mybuf[0],icLen);
scrWidth = mybuf[1] + 256*mybuf[0];    /*screen width*/
scrHeight = mybuf[3] +256*mybuf[2];    /*screen height*/
iDepth = mybuf[8];                     /*bitplanes*/
iCompr = mybuf[10];                    /*compression flag*/
iWidth = mybuf[17] +256*mybuf[16];     /*picture width*/
iHeight =mybuf[19]+256*mybuf[18];      /*picture height*/
iRowBytes = iWidth/8;                  /*picture bytes per row*/
scrRowBytes = scrWidth/8;              /*screen bytes per row*/
nColors = power(2,iDepth);             /*number of colours*/
if (iHeight==200) iHeight=256;
/*set up a bitmap PicBitMap the size of the picture screen*/
/*and allocate raster for it*/
if ((code==1)||(code==16)) return(0);
InitBitMap(bitmap,iDepth,iWidth,iHeight);
for (i=0;i<iDepth;i++)
 {
  if
  ((bitmap->Planes[i] = (PLANEPTR)AllocRaster(scrWidth,scrHeight)) == 0)
  return(FALSE);
  else BltClear (bitmap->Planes[i],scrHeight*scrRowBytes,0);
 }
return(0);
}

/*this chunk contains the colour information*/
readcmap(viewport,code)
struct ViewPort *viewport;
long code;
{
long i,j,lim;
rLen = Read(fHandle,&mybuf[0],icLen);
if(code==1) return(0);
if (code==16) code=0;
lim=(nColors&255);
for (i =code;i<(code+lim);i++)
 {
 j=(i&(nColors-1));
 red = mybuf[j*3];
 gre = mybuf[j*3 + 1];
 blu = mybuf[j*3 + 2];
 SetRGB4(viewport,i,red/16,gre/16,blu/16);
 colormap[3*i] = red/16;
 colormap[1+3*i]=gre/16;
 colormap[2+3*i]=blu/16;
 colormap2[3*i]=red/16;
 colormap2[1+3*i]=gre/16;
 colormap2[2+3*i]=blu/16;
 }
return(0);
}

/*these two routines have nothing to do with reading the file but it*/
/*made things easier to have them in the same module as the colourmap*/

void fadedown(viewport)         /*slowly decrease each colour intensity*/
struct ViewPort *viewport;
{
int i,j;
for(j=0;j<15;j++)
{
for (i=0;i<8;i++)
{
if (colormap2[3*i]) colormap2[3*i]--;
if (colormap2[1+3*i]) colormap2[1+3*i]--;
if (colormap2[2+3*i]) colormap2[2+3*i]--;
SetRGB4(viewport,i,(colormap2[3*i]&15),(colormap2[1+3*i]&15),(colormap2[2+3*i]&15));
}
Delay(2);
}
}
void fadeup(viewport)             /*slowly increase each colour intensity*/
struct ViewPort *viewport;
{
int i,j;
for(j=0;j<15;j++)
{
for (i=0;i<8;i++)
{
if (colormap2[3*i]<colormap[3*i]) colormap2[3*i]++;
if (colormap2[1+3*i]<colormap[1+3*i]) colormap2[1+3*i]++;
if (colormap2[2+3*i]<colormap[2+3*i]) colormap2[2+3*i]++;
SetRGB4(viewport,i,(colormap2[3*i]&15),(colormap2[1+3*i]&15),(colormap2[2+3*i]&15));
}
Delay(2);
}
}

/*the abit chunk of an acbm file can be read straight onto*/
/*the raster*/
readabit(bitmap)
struct BitMap *bitmap;
{
int i;
for (i=0;i<iDepth;i++)
rLen = Read(fHandle,bitmap->Planes[i],scrRowBytes*iHeight);
return(0);
}

/*the body chunk of an ilbm file*/
readbody(bitmap)
struct BitMap *bitmap;
{
tempbuffer=(char *)AllocMem(icLen,65539);     /*allocate temporary*/
                                      /*buffer*/
rLen = Read(fHandle,tempbuffer,icLen);/*read data*/
if (iCompr>1)                         /*test compression*/
                                      /*flag*/
 printf("Unknown Compression Algorithm  \n");
if (iCompr==0) plainread(bitmap);           /*no compression*/
if (iCompr==1) decode(bitmap);              /*normal compression*/
FreeMem(tempbuffer,icLen);            /*free buffer*/
return(0);
}

/*decode a compressed file*/
/*read the next byte inCode*/
/*if inCode<128 read the next inCode+1 bytes normally*/
/*if inCode>128 the next inCode+1 bytes are the same as the next one*/
decode(bitmap)
struct BitMap *bitmap;
{
USHORT rows,planes,columns;
UBYTE bCnt,inCode,inByte;
UBYTE *place;
UBYTE *scrRow;
place= tempbuffer;
for (rows=0;rows<iHeight;rows++)
 {
  for (planes=0;planes<iDepth;planes++)
  {
  scrRow=bitmap->Planes[planes] + (rows*scrRowBytes);
  bCnt=0;
  while(bCnt<iRowBytes)
   {inCode=*(place);
    place++;
    if (inCode<128)
    {for(columns=0;columns<inCode+1;columns++) *(scrRow+bCnt+columns)=*(place++);
     bCnt=bCnt+inCode+1;
    }
    else if (inCode>128)
    {
     inByte= *(place);
     for(columns=0;columns<257-inCode;columns++) *(scrRow+bCnt+columns)=inByte;
     bCnt=bCnt+257-inCode;
     place++;
    }
   }
  }
 }
return(0);
}
/*no compression, but the bitplanes are interleaved*/
plainread(bitmap)
struct BitMap *bitmap;
{
short rows,planes;
long columns;
char *scrRow;
char *pointer=tempbuffer;
for (rows=0;rows<iHeight;rows++)
 {
  for (planes=0;planes<iDepth;planes++)
  {
  scrRow=bitmap->Planes[planes] + rows*scrRowBytes;
  for (columns=0;columns<iRowBytes;columns++)
  *(scrRow+columns)=*(pointer++);
  }
 }
return(0);
}

/*compare strings*/
strcmp(s,t)
char *s, *t;
{
int n=0;
for (; *s == *t; s++,t++,n++)
if (*s == NULL)
return(0);
if(n==4) return(0);
return(*s - *t);
}

/*raise x to the power n*/
power(x,n)
int x,n;
{
int i,p;
p=1;
for (i=1;i<=n; ++i)
p = p*x;
return(p);
}
