home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d185
/
iff.lha
/
EXAMPLES
/
Display
/
myreadpict.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-12-13
|
13KB
|
365 lines
/** myReadPict.c ************************************************************
*
* Read an ILBM raster image file. 23-Jan-86.
*
* Modified version of ReadPict.c
* by Jerry Morrison, Steve Shaw, and Steve Hayes, Electronic Arts.
* This software is in the public domain.
*
* Modified by C. Scheppner 11/86
* Handles CAMG chunks for HAM, etc.
* Calls user defined routine getBitMap(ilbmFramePtr) when it
* reaches the BODY.
* getBitMap() can open a screen of the correct size using
* information this rtn places in the ilbmFrame, and returns
* a pointer to a BitMap structure. The BitMap structure
* tells myReadPicture where it should load the bit planes.
*
* Modified by C. Scheppner 12/86
* Loads in CCRT or CRNG chunks (converts CCRT to CRNG)
* Modified 11-88 to use CCRT, CAMG defs and macros added to ilbm.h
* and existing CRange (not CrngChunk) def in ilbm.h
****************************************************************************/
#define LOCAL static
#include "intuition/intuition.h"
#include "libraries/dos.h"
#include "libraries/dosextens.h"
#include "iff/ilbm.h"
#include "myreadpict.h" /* cs */
/* Define size of a temporary buffer used in unscrambling the ILBM rows.*/
#define bufSz 512
/*------------ ILBM reader -----------------------------------------------*/
/* ILBMFrame is our "client frame" for reading FORMs ILBM in an IFF file.
* We allocate one of these on the stack for every LIST or FORM encountered
* in the file and use it to hold BMHD & CMAP properties. We also allocate
* an initial one for the whole file.
* We allocate a new GroupContext (and initialize it by OpenRIFF or
* OpenRGroup) for every group (FORM, CAT, LIST, or PROP) encountered. It's
* just a context for reading (nested) chunks.
*
* If we were to scan the entire example file outlined below:
* reading proc(s) new new
*
* --whole file-- myReadPicture+ReadIFF GroupContext ILBMFrame
* CAT ReadICat GroupContext
* LIST GetLiILBM+ReadIList GroupContext ILBMFrame
* PROP ILBM GetPrILBM GroupContext
* CMAP GetCMAP
* BMHD GetBMHD
* FORM ILBM GetFoILBM GroupContext ILBMFrame
* BODY GetBODY
* FORM ILBM GetFoILBM GroupContext ILBMFrame
* BODY GetBODY
* FORM ILBM GetFoILBM GroupContext ILBMFrame
*/
/* NOTE: For a small version of this program, set Fancy to 0.
* That'll compile a program that reads a single FORM ILBM in a file, which
* is what DeluxePaint produces. It'll skip all LISTs and PROPs in the input
* file. It will, however, look inside a CAT for a FORM ILBM.
* That's suitable for 90% of the uses.
*
* For a fancier version that handles LISTs and PROPs, set Fancy to 1.
* That'll compile a program that dives into a LIST, if present, to read
* the first FORM ILBM. E.g. a DeluxePrint library of images is a LIST of
* FORMs ILBM.
*
* For an even fancier version, set Fancy to 2. That'll compile a program
* that dives into non-ILBM FORMs, if present, looking for a nested FORM ILBM.
* E.g. a DeluxeVideo C.S. animated object file is a FORM ANBM containing a
* FORM ILBM for each image frame. */
#define Fancy 0
/* Global access to client-provided pointers.*/
LOCAL ILBMFrame *giFrame = NULL; /* "client frame".*/
IFFP handleCAMG(context,frame)
GroupContext *context;
ILBMFrame *frame;
{
IFFP iffp = IFF_OKAY;
frame->foundCAMG = TRUE;
iffp = GetCAMG(context, &frame->camgChunk);
return(iffp);
}
IFFP handleCRNG(context,frame)
GroupContext *context;
ILBMFrame *frame;
{
IFFP iffp = IFF_OKAY;
if(frame->cycleCnt < maxCycles)
{
iffp = GetCRNG(context,&(frame->crngChunks[frame->cycleCnt]));
frame->cycleCnt++;
}
return(iffp);
}
IFFP handleCCRT(context,frame)
GroupContext *context;
ILBMFrame *frame;
{
CcrtChunk ccrtTmp;
CRange *ptCrng;
IFFP iffp = IFF_OKAY;
if(frame->cycleCnt < maxCycles)
{
iffp = GetCCRT(context, &ccrtTmp);
ptCrng = &(frame->crngChunks[frame->cycleCnt]);
if(ccrtTmp.direction) ccrtTmp.direction = -ccrtTmp.direction;
ptCrng->active = ccrtTmp.direction & 0x03;
ptCrng->low = ccrtTmp.start;
ptCrng->high = ccrtTmp.end;
/* Convert CCRT secs/msecs to CRNG timimg
* 0x4000 = max CRNG rate (cycle every 1 60th sec)
* This must be divided by # 60th's between cycles
* seconds to 60th's is easy
* msecs to 60th's requires division by 16667
* this is int math so I add 8334 (half 16667) first for rounding
*/
ptCrng->rate = 0x4000 /
((ccrtTmp.seconds * 60)+((ccrtTmp.microseconds+8334)/16667));
frame->cycleCnt++;
}
return(iffp);
}
/** GetFoILBM() *************************************************************
*
* Called via myReadPictureto handle every FORM encountered in an IFF file.
* Reads FORMs ILBM and skips all others.
* Inside a FORM ILBM, it stops once it reads a BODY. It complains if it
* finds no BODY or if it has no BMHD to decode the BODY.
*
* Once we find a BODY chunk, we'll call user rtn getBitMap() to
* allocate the bitmap and planes (or screen) and then read
* the BODY into the planes.
*
****************************************************************************/
LOCAL BYTE bodyBuffer[bufSz];
IFFP GetFoILBM(parent) GroupContext *parent;
{
/*compilerBug register*/ IFFP iffp;
GroupContext formContext;
ILBMFrame ilbmFrame; /* only used for non-clientFrame fields.*/
struct BitMap *destBitMap; /* cs */
/* Handle a non-ILBM FORM. */
if (parent->subtype != ID_ILBM)
{
#if Fancy >= 2
/* Open a non-ILBM FORM and recursively scan it for ILBMs.*/
iffp = OpenRGroup(parent, &formContext);
CheckIFFP();
do {
iffp = GetF1ChunkHdr(&formContext);
} while (iffp >= IFF_OKAY);
if (iffp == END_MARK)
{
iffp = IFF_OKAY; /* then continue scanning the file */
}
CloseRGroup(&formContext);
return(iffp);
#else
return(IFF_OKAY); /* Just skip this FORM and keep scanning the file.*/
#endif
}
ilbmFrame = *(ILBMFrame *)parent->clientFrame;
iffp = OpenRGroup(parent, &formContext);
CheckIFFP();
do switch (iffp = GetFChunkHdr(&formContext)) {
case ID_BMHD: {
ilbmFrame.foundBMHD = TRUE;
iffp = GetBMHD(&formContext, &ilbmFrame.bmHdr);
break; }
case ID_CAMG: { /* cs */
iffp = handleCAMG(&formContext, &ilbmFrame);
break; }
case ID_CRNG: { /* cs */
iffp = handleCRNG(&formContext, &ilbmFrame);
break; }
case ID_CCRT: { /* cs */
iffp = handleCCRT(&formContext, &ilbmFrame);
break; }
case ID_CMAP: {
ilbmFrame.nColorRegs = maxColorReg; /* room for this many */
iffp = GetCMAP(&formContext, (WORD *)ilbmFrame.colorMap,
&ilbmFrame.nColorRegs);
break; }
case ID_BODY: { /* cs */
if (!ilbmFrame.foundBMHD)
{
iffp = BAD_FORM; /* No BMHD chunk! */
}
else
{
if(destBitMap=(struct BitMap *)getBitMap(&ilbmFrame))
{
iffp = GetBODY( &formContext,
destBitMap,
NULL,
&ilbmFrame.bmHdr,
bodyBuffer,
bufSz);
if (iffp == IFF_OKAY) iffp = IFF_DONE; /* Eureka */
*giFrame = ilbmFrame; /* copy fields to client frame */
}
else
{
iffp = CLIENT_ERROR; /* not enough RAM for the bitmap */
}
}
break; }
case END_MARK: {
iffp = BAD_FORM;
break; }
} while (iffp >= IFF_OKAY);
/* loop if valid ID of ignored chunk or a
* subroutine returned IFF_OKAY (no errors).*/
if (iffp != IFF_DONE) return(iffp);
CloseRGroup(&formContext);
return(iffp);
}
/** Notes on extending GetFoILBM ********************************************
*
* To read more kinds of chunks, just add clauses to the switch statement.
* To read more kinds of property chunks (GRAB, CAMG, etc.) add clauses to
* the switch statement in GetPrILBM, too.
*
* To read a FORM type that contains a variable number of data chunks--e.g.
* a FORM FTXT with any number of CHRS chunks--replace the ID_BODY case with
* an ID_CHRS case that doesn't set iffp = IFF_DONE, and make the END_MARK
* case do whatever cleanup you need.
*
****************************************************************************/
/** GetPrILBM() *************************************************************
*
* Called via myReadPicture to handle every PROP encountered in an IFF file.
* Reads PROPs ILBM and skips all others.
*
****************************************************************************/
#if Fancy
IFFP GetPrILBM(parent) GroupContext *parent; {
/*compilerBug register*/ IFFP iffp;
GroupContext propContext;
ILBMFrame *ilbmFrame = (ILBMFrame *)parent->clientFrame;
if (parent->subtype != ID_ILBM)
return(IFF_OKAY); /* just continue scaning the file */
iffp = OpenRGroup(parent, &propContext);
CheckIFFP();
do switch (iffp = GetPChunkHdr(&propContext)) {
case ID_BMHD: {
ilbmFrame->foundBMHD = TRUE;
iffp = GetBMHD(&propContext, &ilbmFrame->bmHdr);
break; }
case ID_CAMG: { /* cs */
iffp = handleCAMG(&propContext, ilbmFrame);
break; }
case ID_CRNG: { /* cs */
iffp = handleCRNG(&propContext, ilbmFrame);
break; }
case ID_CCRT: { /* cs */
iffp = handleCCRT(&propContext, ilbmFrame);
break; }
case ID_CMAP: {
ilbmFrame->nColorRegs = maxColorReg; /* room for this many */
iffp = GetCMAP(&propContext,
(WORD *)&ilbmFrame->colorMap,
&ilbmFrame->nColorRegs);
break; }
} while (iffp >= IFF_OKAY);
/* loop if valid ID of ignored chunk or a
* subroutine returned IFF_OKAY (no errors).*/
CloseRGroup(&propContext);
return(iffp == END_MARK ? IFF_OKAY : iffp);
}
#endif
/** GetLiILBM() *************************************************************
*
* Called via myReadPicture to handle every LIST encountered in an IFF file.
*
****************************************************************************/
#if Fancy
IFFP GetLiILBM(parent) GroupContext *parent; {
ILBMFrame newFrame; /* allocate a new Frame */
newFrame = *(ILBMFrame *)parent->clientFrame; /* copy parent frame */
return( ReadIList(parent, (ClientFrame *)&newFrame) );
}
#endif
/** myReadPicture() ********************************************************/
IFFP myReadPicture(file,iFrame)
LONG file;
ILBMFrame *iFrame; /* Top level "client frame".*/
{
IFFP iffp = IFF_OKAY;
#if Fancy
iFrame->clientFrame.getList = GetLiILBM;
iFrame->clientFrame.getProp = GetPrILBM;
#else
iFrame->clientFrame.getList = SkipGroup;
iFrame->clientFrame.getProp = SkipGroup;
#endif
iFrame->clientFrame.getForm = GetFoILBM;
iFrame->clientFrame.getCat = ReadICat ;
/* Initialize the top-level client frame's property settings to the
* program-wide defaults. This example just records that we haven't read
* any BMHD property or CMAP color registers yet. For the color map, that
* means the default is to leave the machine's color registers alone.
* If you want to read a property like GRAB, init it here to (0, 0). */
iFrame->foundBMHD = FALSE;
iFrame->nColorRegs = 0;
iFrame->foundCAMG = FALSE; /* cs */
iFrame->cycleCnt = 0; /* cs */
giFrame = iFrame;
/* Store a pointer to the client's frame in a global variable so that
* GetFoILBM can update client's frame when done. Why do we have so
* many frames & frame pointers floating around causing confusion?
* Because IFF supports PROPs which apply to all FORMs in a LIST,
* unless a given FORM overrides some property.
* When you write code to read several FORMs,
* it is ssential to maintain a frame at each level of the syntax
* so that the properties for the LIST don't get overwritten by any
* properties specified by individual FORMs.
* We decided it was best to put that complexity into this one-FORM example,
* so that those who need it later will have a useful starting place.
*/
iffp = ReadIFF(file, (ClientFrame *)iFrame);
return(iffp);
}