/* IFFStuff.c ***************************************************************
*
*	IFFStuff ------	Dieses Programmfragment stellt einen kleinen
*			Auszug aus meinen berüchtigten "ImageTools"
*			dar. Die Routinen dienen zum Laden von IFF-
*			ILBM-Dateien in Image-Strukturen.
*
*****************************************************************************
*
*	Autor...
*
*	Olaf Barthel & ED Electronic Design Hannover
*	Brabeckstraße 35
*	D-3000 Hannover 71
*
*	Bundesrepublik Deutschland
*
****************************************************************************/
#include <intuition/intuition.h>
#include <exec/memory.h>
#include <stdio.h>

	/* Mit diesem Makro wird der Speicherbedarf einer Zeile
	   Graphik in USHORTs berechnet. */

#define byte(n)	(((n + 15) >> 4) << 1)

	/* BitMapHeader : enthält Informationen über das zu ladende
	   Bild. */

typedef struct
{
	UWORD w,h;
	UWORD x,y;
	UBYTE nPlanes;
	UBYTE masking;
	UBYTE compression;
	UBYTE pad1;
	UWORD transparentColor;
	UBYTE xAspect, yAspect;
	WORD pageWidth, pageHeight;
} BitMapHeader;

	/* Vorwärtsdeklarationen, um Warnings zu vermeiden. */

void *AllocMem(),FreeMem();

	/* FindChunk(ChunkName,FilePointer):

		Sucht in einer Datei nach einem vier Zeichen langen
		Chunknamen. */

BOOL
FindChunk(ChunkName,FilePointer)
register char *ChunkName;
register FILE *FilePointer;
{
	register char NextByte;

	while(!feof(FilePointer))
	{
		NextByte = fgetc(FilePointer);

TryAgain:	if(NextByte == ChunkName[0])
		{
			NextByte = fgetc(FilePointer);

			if(NextByte != ChunkName[1])
				goto TryAgain;

			NextByte = fgetc(FilePointer);

			if(NextByte != ChunkName[2])
				goto TryAgain;

			NextByte = fgetc(FilePointer);

			if(NextByte != ChunkName[3])
				goto TryAgain;

			return(TRUE);
		}
	}

	return(FALSE);
}

	/* LoadImage(FileName,Image):

		Bereitet ein Image auf ein zu ladendes Bild vor. */

BOOL
LoadImage(FileName,Image)
char *FileName;
struct Image *Image;
{
	register LONG i;
	FILE *ImgFile;
	BitMapHeader BMHeader;

	if(!(ImgFile = fopen(FileName,"r")))
		return(FALSE);

	if(!FindChunk("BMHD",ImgFile))
	{
		fclose(ImgFile);
		return(FALSE);
	}

	for(i = 0 ; i < sizeof(LONG) ; i++)
		fgetc(ImgFile);

	fread(&BMHeader,sizeof(BitMapHeader),1,ImgFile);

	Image -> Width		= BMHeader . w;
	Image -> Height		= BMHeader . h;
	Image -> Depth		= BMHeader . nPlanes;
	Image -> PlanePick	= (1 << BMHeader . nPlanes) - 1;
	Image -> PlaneOnOff	= 0x00;
	Image -> LeftEdge	= 0;
	Image -> TopEdge	= 0;

	fclose(ImgFile);

	return(TRUE);
}

	/* LoadRaster(FileName):

		Besorgt Speicher für ein zu ladendes Bild und
		lädt die Daten anschließend hinein. */

USHORT *
LoadRaster(FileName)
char *FileName;
{
	register LONG i,j,k;
	UBYTE Value,SoFar,Compr,Planes;
	BYTE ChkVal;
	LONG Height,Width;
	USHORT *Data;
	PLANEPTR Plane[8];
	FILE *PicFile;
	BitMapHeader BMHeader;

	if(!(PicFile = fopen(FileName,"r")))
		return(NULL);

	if(!FindChunk("BMHD",PicFile))
	{
		fclose(PicFile);
		return(NULL);
	}

	for(i = 0 ; i < sizeof(LONG) ; i++)
		fgetc(PicFile);

	fread(&BMHeader,(LONG)sizeof(BitMapHeader),1L,PicFile);

	Width	= byte(BMHeader . w);
	Height	= BMHeader . h;
	Planes	= BMHeader . nPlanes;
	Compr	= BMHeader . compression;

	if(Compr > 1)
	{
		fclose(PicFile);
		return(NULL);
	}

	if(!(Data = (USHORT *)AllocMem(Width * Height * Planes,MEMF_CHIP)))
	{
		fclose(PicFile);
		return(NULL);
	}

	if(!FindChunk("BODY",PicFile))
	{
		FreeMem(Data,Width * Height * Planes);

		fclose(PicFile);
		return(NULL);
	}

	for(i = 0 ; i < sizeof(LONG) ; i++)
		fgetc(PicFile);

	for(i = 0 ; i < Planes ; i++)
		Plane[i] = (PLANEPTR)Data + (Width * Height * i);

	if(Compr == 0)
	{
		for(k = 0 ; k < Height ; k++)
		{
			for(j = 0 ; j < Planes ; j++)
			{
				for(i = 0 ; i < Width ; i++)
				{
					Value = fgetc(PicFile);

					*Plane[j] = Value;
					Plane[j]++;
				}
			}
		}
	}

	if(Compr == 1)
	{
		for(k = 0 ; k < Height ; k++)
		{
			for(j = 0 ; j < Planes ; j++)
			{
				for(SoFar = 0 ; SoFar < Width ; )
				{
					ChkVal = fgetc(PicFile);

					if(ChkVal > 0)
					{
						for(i = 0 ; i <= ChkVal ; i++)
						{
							Value = fgetc(PicFile);

							*Plane[j] = Value;
							Plane[j]++;
							SoFar++;
						}
					}
					else
					{
						if(ChkVal != 128)
						{
							Value = fgetc(PicFile);

							for(i = 0 ; i <= -ChkVal ; i++)
							{
								*Plane[j] = Value;
								Plane[j]++;
								SoFar++;
							}
						}
					}
				}
			}
		}
	}

	fclose(PicFile);

	return(Data);
}

	/* FreeImageData(Image):

		Gibt den von einem Image belegten Speicher frei. */

void
FreeImageData(Image)
register struct Image *Image;
{
	if(Image -> ImageData)
	{
		FreeMem(Image -> ImageData,byte(Image -> Width) * Image -> Height * Image -> Depth);
		Image -> ImageData = NULL;
	}
}
