
/*Amiga Computing*/
/*iff files*/
/*c source code*/

/*this program was inspired by the Basic Program
LoadILBM-SaveACBM by Carolyn Scheppner*/

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

struct ViewPort *WVP;               /*screen ViewPort*/
struct BitMap PicBitMap;            /*picture BitMap*/
struct BitMap ScreenBitMap;         /*screen BitMap*/
long libraries=0;
long i,k;                           /*loop variables*/
short j;
struct GfxBase *GfxBase;            /*graphics base*/
struct IntuitionBase *IntuitionBase;/*intuition base*/
struct Screen *CustScr;             /*pointer to screen structure*/
struct Window *Wdw;                 /*pointer to window structure*/
char *filename = "piccy";           /*this could be any
                                        lo-res ILBM file*/
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*/
long rLen;               /*bytes read from disc*/
char *tempbuffer;        /*temporary buffer for body chunk*/
long fHandle;            /*file handle*/
char red,gre,blu;        /*temporary colour variables*/
int camgModes;           /*camg modes*/

 /*standard full size lo-res screen*/
static  struct NewScreen NewCustScr =
{
0,0,
320,
256,
5,
3,1,
SPRITES,
CUSTOMSCREEN | CUSTOMBITMAP,
0,
NULL,
NULL,
&ScreenBitMap,
};
 /*full size window for screen*/
static  struct NewWindow NewWdw =
{
0,0,
320,
256,
3,1,
MOUSEBUTTONS|CLOSEWINDOW,
SUPER_BITMAP | ACTIVATE
 | BORDERLESS|WINDOWCLOSE,
NULL,
NULL,
NULL,
NULL,
&ScreenBitMap,
0,0,
0,0,
CUSTOMSCREEN
};

main()
{

libraries= openlibraries();   /*open the libraries*/
if (libraries == 0) exit(1);
openfile();                   /*open the file and read*/
                              /*header*/
init();                       /*open screen and window*/
while (bytesread<totalbytes) readchunk();
/*copy picture on to screen*/
BltBitMap(&PicBitMap,0,0,&ScreenBitMap,0,0,scrWidth,scrHeight,0xc0,0xff,0);
Wait(1<<Wdw->UserPort->mp_SigBit);
cleanup();
closelibraries();
return(0);
}

openlibraries()              /*open the libraries*/
{
GfxBase= (struct GfxBase *)OpenLibrary("graphics.library",0);
if (GfxBase == 0) return(0);
IntuitionBase= (struct IntuitionBase *)OpenLibrary("intuition.library",0);
if (IntuitionBase == 0) return(0);
return(1);
}

/*set up a lo-res screen and window*/
init()
{
InitBitMap(&ScreenBitMap,5,320,256);  /*set up a bitmap */
for(i=0;i<5;i++)                      /*allocate screen for it*/
 {
  ScreenBitMap.Planes[i] = (PLANEPTR)AllocRaster(320,256);
  if (ScreenBitMap.Planes[i] == 0) exit(2);
  BltClear(ScreenBitMap.Planes[i],40*256,0); /*clear the screen*/
 }
CustScr= (struct Screen *) OpenScreen(&NewCustScr);
if (CustScr == 0) exit(1);                 /*open the screen*/
NewWdw.BitMap=(struct BitMap *) &ScreenBitMap;
NewWdw.Screen = CustScr;                  /*open the window*/
Wdw = (struct Window *)OpenWindow(&NewWdw);
if (Wdw  == NULL) exit(FALSE);
WVP=(struct ViewPort *)ViewPortAddress(Wdw);
return(0);
}

/*close windows and screens, free rasters,close file*/
cleanup()
{
int i;
CloseWindow(Wdw);
CloseScreen(CustScr);
for (i=0;i<5;i++)
 {
  FreeRaster(ScreenBitMap.Planes[i],320,256);
 }
for (i=0;i<iDepth;i++)
 {
  FreeRaster(PicBitMap.Planes[i],scrWidth,scrHeight);
 }
Close(fHandle);
return(0);
}

closelibraries()               /*close libraries*/
{
CloseLibrary(GfxBase);
CloseLibrary(IntuitionBase);
return(0);
}

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

readbitmapheader()
{
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*/

/*set up a bitmap PicBitMap the size of the picture screen*/
/*and allocate raster for it*/
InitBitMap(&PicBitMap,iDepth,scrWidth,scrHeight);
for (i=0;i<iDepth;i++)
 {
  if
  ((PicBitMap.Planes[i] = (PLANEPTR)AllocRaster(scrWidth,scrHeight)) == 0)
  exit(FALSE);
  else BltClear (PicBitMap.Planes[i],scrHeight*scrRowBytes,0);
 }
return(0);
}

/*this chunk contains the colour information*/
readcmap()
{
rLen = Read(fHandle,&mybuf[0],icLen);
for (i =0;i<nColors;i++)
 {
 red = mybuf[i*3];
 gre = mybuf[i*3 + 1];
 blu = mybuf[i*3 + 2];
 colormap[i] = 16*red +gre  +blu/16;
 }
/*change the screen colours*/
LoadRGB4(WVP,&colormap[0],nColors);
return(0);
}


/*the abit chunk of an acbm file can be read straight onto*/
/*the raster*/
readabit()
{
for (i=0;i<iDepth;i++)
rLen = Read(fHandle,PicBitMap.Planes[i],scrRowBytes*scrHeight);
return(0);
}

/*the body chunk of an ilbm file*/
readbody()
{
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();           /*no compression*/
if (iCompr==1) decode();              /*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()
{
USHORT rows,planes,columns;
UBYTE bCnt,inCode,inByte;
UBYTE *place;
UBYTE *scrRow;
place= (UBYTE *)tempbuffer;
for (rows=0;rows<iHeight;rows++)
 {
  for (planes=0;planes<iDepth;planes++)
  {
  scrRow=PicBitMap.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()
{
short rows,planes;
long columns;
char *scrRow;
char *pointer=tempbuffer;
for (rows=0;rows<iHeight;rows++)
 {
  for (planes=0;planes<iDepth;planes++)
  {
  scrRow=(char *)(PicBitMap.Planes[planes] + rows*scrRowBytes);
  for (columns=0;columns<iRowBytes;columns++)
  *(scrRow+columns)=*(pointer++);
  }
 }
return(0);
}

/*compare strings*/
strcmp(s,t)
char *s, *t;
{
for (; *s == *t; s++,t++)
if (*s == NULL)
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);
}
